[#1223] lens/tui: Abandon parsers
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
This commit is contained in:
parent
08f9fc4738
commit
c72bc6596a
23 changed files with 784 additions and 1118 deletions
106
cmd/frostfs-lens/internal/schema/handler.go
Normal file
106
cmd/frostfs-lens/internal/schema/handler.go
Normal file
|
@ -0,0 +1,106 @@
|
|||
package schema
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/types/bucket"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/types/common"
|
||||
)
|
||||
|
||||
type HandlerOutput struct {
|
||||
Result common.Result
|
||||
Next Handler
|
||||
}
|
||||
|
||||
type Handler func(key, val []byte) (HandlerOutput, error)
|
||||
|
||||
func NewHandler(options ...HandlerOutput) Handler {
|
||||
return func(key, val []byte) (HandlerOutput, error) {
|
||||
for _, opt := range options {
|
||||
if err := common.TryDecode(key, val, opt.Result); err == nil {
|
||||
if opt.Next == nil {
|
||||
opt.Next = NewHandler()
|
||||
}
|
||||
return opt, nil
|
||||
}
|
||||
}
|
||||
return HandlerOutput{}, errors.New("no handler matched")
|
||||
}
|
||||
}
|
||||
|
||||
var x = []HandlerOutput{
|
||||
{
|
||||
Result: &bucket.Graveyard{},
|
||||
},
|
||||
{
|
||||
Result: &bucket.Garbage{},
|
||||
},
|
||||
{
|
||||
Result: &bucket.ContainerVolume{},
|
||||
},
|
||||
{
|
||||
Result: &bucket.Locked{},
|
||||
Next: NewHandler(
|
||||
HandlerOutput{
|
||||
Result: &bucket.LockedSubbucket{},
|
||||
},
|
||||
),
|
||||
},
|
||||
{
|
||||
Result: &bucket.ShardInfo{},
|
||||
},
|
||||
{
|
||||
Result: &bucket.Object{},
|
||||
// Next: NewHandler(
|
||||
// HandlerOutput{
|
||||
// Result: &record.Object{},
|
||||
// },
|
||||
// ),
|
||||
},
|
||||
{
|
||||
Result: &bucket.Small{},
|
||||
},
|
||||
{
|
||||
Result: &bucket.Root{},
|
||||
},
|
||||
{
|
||||
Result: &bucket.Owner{},
|
||||
Next: NewHandler(
|
||||
HandlerOutput{
|
||||
Result: &bucket.OwnerSubbucket{},
|
||||
},
|
||||
),
|
||||
},
|
||||
{
|
||||
Result: &bucket.Attribute{},
|
||||
Next: NewHandler(
|
||||
HandlerOutput{
|
||||
Result: &bucket.AttributeSubbucket{},
|
||||
},
|
||||
),
|
||||
},
|
||||
{
|
||||
Result: &bucket.PayloadHash{},
|
||||
// Next: NewHandler(
|
||||
// HandlerOutput{
|
||||
// Result: &record.PayloadHash{},
|
||||
// },
|
||||
// ),
|
||||
},
|
||||
{
|
||||
Result: &bucket.Parent{},
|
||||
},
|
||||
{
|
||||
Result: &bucket.Split{},
|
||||
},
|
||||
{
|
||||
Result: &bucket.ContainerCounters{},
|
||||
},
|
||||
{
|
||||
Result: &bucket.ECInfo{},
|
||||
},
|
||||
}
|
||||
|
||||
func Start() Handler {
|
||||
return NewHandler(x...)
|
||||
}
|
44
cmd/frostfs-lens/internal/schema/types/bucket/filter.go
Normal file
44
cmd/frostfs-lens/internal/schema/types/bucket/filter.go
Normal file
|
@ -0,0 +1,44 @@
|
|||
package bucket
|
||||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/types/filter"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
)
|
||||
|
||||
var (
|
||||
_ (filter.HasCID) = (*Object)(nil)
|
||||
_ (filter.HasCID) = (*Small)(nil)
|
||||
_ (filter.HasCID) = (*Root)(nil)
|
||||
_ (filter.HasCID) = (*PayloadHash)(nil)
|
||||
_ (filter.HasCID) = (*Parent)(nil)
|
||||
_ (filter.HasCID) = (*Split)(nil)
|
||||
_ (filter.HasCID) = (*ECInfo)(nil)
|
||||
)
|
||||
|
||||
func (b *Object) HasCID(id cid.ID) bool {
|
||||
return b.id.Equals(id)
|
||||
}
|
||||
|
||||
func (b *Small) HasCID(id cid.ID) bool {
|
||||
return b.id.Equals(id)
|
||||
}
|
||||
|
||||
func (b *Root) HasCID(id cid.ID) bool {
|
||||
return b.id.Equals(id)
|
||||
}
|
||||
|
||||
func (b *PayloadHash) HasCID(id cid.ID) bool {
|
||||
return b.id.Equals(id)
|
||||
}
|
||||
|
||||
func (b *Parent) HasCID(id cid.ID) bool {
|
||||
return b.id.Equals(id)
|
||||
}
|
||||
|
||||
func (b *Split) HasCID(id cid.ID) bool {
|
||||
return b.id.Equals(id)
|
||||
}
|
||||
|
||||
func (b *ECInfo) HasCID(id cid.ID) bool {
|
||||
return b.id.Equals(id)
|
||||
}
|
75
cmd/frostfs-lens/internal/schema/types/bucket/string.go
Normal file
75
cmd/frostfs-lens/internal/schema/types/bucket/string.go
Normal file
|
@ -0,0 +1,75 @@
|
|||
package bucket
|
||||
|
||||
import "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/types/common"
|
||||
|
||||
func (b *Graveyard) String() string {
|
||||
return b.prefix.String()
|
||||
}
|
||||
|
||||
func (b *Garbage) String() string {
|
||||
return b.prefix.String()
|
||||
}
|
||||
|
||||
func (b *ContainerVolume) String() string {
|
||||
return b.prefix.String()
|
||||
}
|
||||
|
||||
func (b *Locked) String() string {
|
||||
return b.prefix.String()
|
||||
}
|
||||
|
||||
func (b *LockedSubbucket) String() string {
|
||||
return b.id.String()
|
||||
}
|
||||
|
||||
func (b *ShardInfo) String() string {
|
||||
return b.prefix.String()
|
||||
}
|
||||
|
||||
func (b *Object) String() string {
|
||||
return common.JoinWithSpace(b.prefix, b.id)
|
||||
}
|
||||
|
||||
func (b *Small) String() string {
|
||||
return common.JoinWithSpace(b.prefix, b.id)
|
||||
}
|
||||
|
||||
func (b *Root) String() string {
|
||||
return common.JoinWithSpace(b.prefix, b.id)
|
||||
}
|
||||
|
||||
func (b *Owner) String() string {
|
||||
return common.JoinWithSpace(b.prefix, b.id)
|
||||
}
|
||||
|
||||
func (b *OwnerSubbucket) String() string {
|
||||
return b.id.String()
|
||||
}
|
||||
|
||||
func (b *Attribute) String() string {
|
||||
return common.JoinWithSpace(b.prefix, b.id, b.key)
|
||||
}
|
||||
|
||||
func (b *AttributeSubbucket) String() string {
|
||||
return b.val
|
||||
}
|
||||
|
||||
func (b *PayloadHash) String() string {
|
||||
return common.JoinWithSpace(b.prefix, b.id)
|
||||
}
|
||||
|
||||
func (b *Parent) String() string {
|
||||
return common.JoinWithSpace(b.prefix, b.id)
|
||||
}
|
||||
|
||||
func (b *Split) String() string {
|
||||
return common.JoinWithSpace(b.prefix, b.id)
|
||||
}
|
||||
|
||||
func (b *ContainerCounters) String() string {
|
||||
return b.prefix.String()
|
||||
}
|
||||
|
||||
func (b *ECInfo) String() string {
|
||||
return common.JoinWithSpace(b.prefix, b.id)
|
||||
}
|
322
cmd/frostfs-lens/internal/schema/types/bucket/types.go
Normal file
322
cmd/frostfs-lens/internal/schema/types/bucket/types.go
Normal file
|
@ -0,0 +1,322 @@
|
|||
package bucket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/types/common"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
"github.com/mr-tron/base58"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidLength = errors.New("invalid name length")
|
||||
ErrInvalidPrefix = errors.New("invalid name prefix")
|
||||
)
|
||||
|
||||
type (
|
||||
Graveyard struct {
|
||||
prefix common.Prefix
|
||||
}
|
||||
|
||||
Garbage struct {
|
||||
prefix common.Prefix
|
||||
}
|
||||
|
||||
ContainerVolume struct {
|
||||
prefix common.Prefix
|
||||
}
|
||||
|
||||
Locked struct {
|
||||
prefix common.Prefix
|
||||
}
|
||||
|
||||
LockedSubbucket struct {
|
||||
id cid.ID
|
||||
}
|
||||
|
||||
ShardInfo struct {
|
||||
prefix common.Prefix
|
||||
}
|
||||
|
||||
Object struct {
|
||||
prefix common.Prefix
|
||||
id cid.ID
|
||||
}
|
||||
|
||||
Small struct {
|
||||
prefix common.Prefix
|
||||
id cid.ID
|
||||
}
|
||||
|
||||
Root struct {
|
||||
prefix common.Prefix
|
||||
id cid.ID
|
||||
}
|
||||
|
||||
Owner struct {
|
||||
prefix common.Prefix
|
||||
id cid.ID
|
||||
}
|
||||
|
||||
OwnerSubbucket struct {
|
||||
id user.ID
|
||||
}
|
||||
|
||||
Attribute struct {
|
||||
prefix common.Prefix
|
||||
id cid.ID
|
||||
key string
|
||||
}
|
||||
|
||||
AttributeSubbucket struct {
|
||||
val string
|
||||
}
|
||||
|
||||
PayloadHash struct {
|
||||
prefix common.Prefix
|
||||
id cid.ID
|
||||
}
|
||||
|
||||
Parent struct {
|
||||
prefix common.Prefix
|
||||
id cid.ID
|
||||
}
|
||||
|
||||
Split struct {
|
||||
prefix common.Prefix
|
||||
id cid.ID
|
||||
}
|
||||
|
||||
ContainerCounters struct {
|
||||
prefix common.Prefix
|
||||
}
|
||||
|
||||
ECInfo struct {
|
||||
prefix common.Prefix
|
||||
id cid.ID
|
||||
}
|
||||
)
|
||||
|
||||
func (b *Graveyard) Decode(name, _ []byte) (err error) {
|
||||
if len(name) != 1 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
if b.prefix = common.Prefix(name[0]); b.prefix != common.Graveyard {
|
||||
return ErrInvalidPrefix
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Garbage) Decode(name, _ []byte) (err error) {
|
||||
if len(name) != 1 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
if b.prefix = common.Prefix(name[0]); b.prefix != common.Garbage {
|
||||
return ErrInvalidPrefix
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *ContainerVolume) Decode(name, _ []byte) (err error) {
|
||||
if len(name) != 1 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
if b.prefix = common.Prefix(name[0]); b.prefix != common.ContainerVolume {
|
||||
return ErrInvalidPrefix
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Locked) Decode(name, _ []byte) (err error) {
|
||||
if len(name) != 1 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
if b.prefix = common.Prefix(name[0]); b.prefix != common.Locked {
|
||||
return ErrInvalidPrefix
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *LockedSubbucket) Decode(name, _ []byte) (err error) {
|
||||
if len(name) != 32 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
if err = b.id.Decode(name); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *ShardInfo) Decode(name, _ []byte) (err error) {
|
||||
if len(name) != 1 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
if b.prefix = common.Prefix(name[0]); b.prefix != common.ShardInfo {
|
||||
return ErrInvalidPrefix
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Object) Decode(name, _ []byte) (err error) {
|
||||
if len(name) != 33 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
switch b.prefix = common.Prefix(name[0]); b.prefix {
|
||||
case common.Primary:
|
||||
case common.Lockers:
|
||||
case common.Tombstone:
|
||||
default:
|
||||
return ErrInvalidPrefix
|
||||
}
|
||||
if err = b.id.Decode(name[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Small) Decode(name, _ []byte) (err error) {
|
||||
if len(name) != 33 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
if b.prefix = common.Prefix(name[0]); b.prefix != common.Small {
|
||||
return ErrInvalidPrefix
|
||||
}
|
||||
if err = b.id.Decode(name[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Root) Decode(name, _ []byte) (err error) {
|
||||
if len(name) != 33 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
if b.prefix = common.Prefix(name[0]); b.prefix != common.Root {
|
||||
return ErrInvalidPrefix
|
||||
}
|
||||
if err = b.id.Decode(name[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Owner) Decode(name, _ []byte) (err error) {
|
||||
if len(name) != 33 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
if b.prefix = common.Prefix(name[0]); b.prefix != common.Owner {
|
||||
return ErrInvalidPrefix
|
||||
}
|
||||
if err = b.id.Decode(name[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *OwnerSubbucket) Decode(name, _ []byte) (err error) {
|
||||
if err = b.id.DecodeString(base58.Encode(name)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Attribute) Decode(name, _ []byte) (err error) {
|
||||
if len(name) < 34 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
if b.prefix = common.Prefix(name[0]); b.prefix != common.UserAttribute {
|
||||
return ErrInvalidPrefix
|
||||
}
|
||||
if err = b.id.Decode(name[1:33]); err != nil {
|
||||
return err
|
||||
}
|
||||
b.key = string(name[33:])
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *AttributeSubbucket) Decode(name, _ []byte) (err error) {
|
||||
if len(name) == 0 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
b.val = string(name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *PayloadHash) Decode(name, _ []byte) (err error) {
|
||||
if len(name) != 33 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
if b.prefix = common.Prefix(name[0]); b.prefix != common.PayloadHash {
|
||||
return ErrInvalidPrefix
|
||||
}
|
||||
if err = b.id.Decode(name[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Parent) Decode(name, _ []byte) (err error) {
|
||||
if len(name) != 33 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
if b.prefix = common.Prefix(name[0]); b.prefix != common.Parent {
|
||||
return ErrInvalidPrefix
|
||||
}
|
||||
if err = b.id.Decode(name[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Split) Decode(name, _ []byte) (err error) {
|
||||
if len(name) != 33 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
if b.prefix = common.Prefix(name[0]); b.prefix != common.Split {
|
||||
return ErrInvalidPrefix
|
||||
}
|
||||
if err = b.id.Decode(name[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *ContainerCounters) Decode(name, _ []byte) (err error) {
|
||||
if len(name) != 1 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
if b.prefix = common.Prefix(name[0]); b.prefix != common.ContainerCounters {
|
||||
return ErrInvalidPrefix
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *ECInfo) Decode(name, _ []byte) (err error) {
|
||||
if len(name) != 33 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
|
||||
if b.prefix = common.Prefix(name[0]); b.prefix != common.ECInfo {
|
||||
return ErrInvalidPrefix
|
||||
}
|
||||
if err = b.id.Decode(name[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
//go:generate stringer -type=Prefix
|
||||
|
||||
package types
|
||||
package common
|
||||
|
||||
import "fmt"
|
||||
|
15
cmd/frostfs-lens/internal/schema/types/common/result.go
Normal file
15
cmd/frostfs-lens/internal/schema/types/common/result.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package common
|
||||
|
||||
type Result interface {
|
||||
String() string
|
||||
// DetailedString() string
|
||||
|
||||
Decode(key, value []byte) error
|
||||
}
|
||||
|
||||
func TryDecode[T Result](key, value []byte, x T) error {
|
||||
if err := x.Decode(key, value); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
53
cmd/frostfs-lens/internal/schema/types/common/util.go
Normal file
53
cmd/frostfs-lens/internal/schema/types/common/util.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
func DecodeOIDs(data []byte) ([]oid.ID, error) {
|
||||
r := io.NewBinReaderFromBuf(data)
|
||||
|
||||
size := r.ReadVarUint()
|
||||
oids := make([]oid.ID, size)
|
||||
|
||||
var i uint64
|
||||
for ; i < size; i++ {
|
||||
if err := oids[i].Decode(r.ReadVarBytes()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return oids, nil
|
||||
}
|
||||
|
||||
func JoinWithSpace(xs ...any) string {
|
||||
if len(xs) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
b := strings.Builder{}
|
||||
|
||||
xs, last := xs[:len(xs)-1], xs[len(xs)-1]
|
||||
|
||||
for _, x := range xs {
|
||||
b.WriteString(getString(x))
|
||||
b.WriteString(" ")
|
||||
}
|
||||
b.WriteString(getString(last))
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func getString(x any) string {
|
||||
switch y := x.(type) {
|
||||
case string:
|
||||
return y
|
||||
case fmt.Stringer:
|
||||
return y.String()
|
||||
default:
|
||||
panic("can't create joined string, got neither string nor Stringer")
|
||||
}
|
||||
}
|
22
cmd/frostfs-lens/internal/schema/types/filter/filter.go
Normal file
22
cmd/frostfs-lens/internal/schema/types/filter/filter.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package filter
|
||||
|
||||
import (
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
)
|
||||
|
||||
type HasCID interface {
|
||||
HasCID(id cid.ID) bool
|
||||
}
|
||||
|
||||
type HasOID interface {
|
||||
HasOID(id oid.ID) bool
|
||||
}
|
||||
|
||||
type HasAttrKey interface {
|
||||
HasAttrKey(key string) bool
|
||||
}
|
||||
|
||||
type HasAttrVal interface {
|
||||
HasAttrVal(val string) bool
|
||||
}
|
12
cmd/frostfs-lens/internal/schema/types/record/filter.go
Normal file
12
cmd/frostfs-lens/internal/schema/types/record/filter.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package record
|
||||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/types/filter"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
)
|
||||
|
||||
var _ (filter.HasOID) = (*Object)(nil)
|
||||
|
||||
func (r *Object) HasOID(id oid.ID) bool {
|
||||
return r.id.Equals(id)
|
||||
}
|
57
cmd/frostfs-lens/internal/schema/types/record/types.go
Normal file
57
cmd/frostfs-lens/internal/schema/types/record/types.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
package record
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/types/common"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
)
|
||||
|
||||
type Record interface {
|
||||
Decode(key []byte, val []byte) (err error)
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidKeyLength = errors.New("invalid key length")
|
||||
ErrInvalidValLength = errors.New("invalid value length")
|
||||
)
|
||||
|
||||
type (
|
||||
Object struct {
|
||||
id oid.ID
|
||||
object objectSDK.Object
|
||||
}
|
||||
|
||||
PayloadHash struct {
|
||||
checksum checksum.Checksum
|
||||
ids []oid.ID
|
||||
}
|
||||
)
|
||||
|
||||
func (r *Object) Decode(key []byte, val []byte) (err error) {
|
||||
if len(key) != 32 {
|
||||
return ErrInvalidKeyLength
|
||||
}
|
||||
|
||||
if err = r.id.Decode(key); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = r.object.Unmarshal(val); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *PayloadHash) Decode(key []byte, val []byte) (err error) {
|
||||
if len(key) != 32 {
|
||||
return ErrInvalidKeyLength
|
||||
}
|
||||
|
||||
r.checksum.SetSHA256([32]byte(key))
|
||||
if r.ids, err = common.DecodeOIDs(val); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -4,7 +4,8 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
|
||||
handlers "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/schema"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/types/common"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
|
@ -24,8 +25,8 @@ type Bucket struct {
|
|||
name []byte
|
||||
path [][]byte
|
||||
|
||||
nextHandler handlers.Handler
|
||||
result *handlers.KV
|
||||
nextHandler schema.Handler
|
||||
result common.Result
|
||||
}
|
||||
|
||||
type Record struct {
|
||||
|
@ -33,7 +34,7 @@ type Record struct {
|
|||
value []byte
|
||||
path [][]byte
|
||||
// nextHandler handlers.Handler
|
||||
result *handlers.KV
|
||||
result common.Result
|
||||
}
|
||||
|
||||
type Application struct {
|
||||
|
|
|
@ -2,30 +2,30 @@ package tuiutil
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
handlers "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/schema"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
func (a *Application) newBucketsView(ctx context.Context, cnr *cid.ID, obj *oid.ID) (tview.Primitive, error) {
|
||||
func (a *Application) newBucketsView(ctx context.Context, _ *cid.ID, _ *oid.ID) (tview.Primitive, error) {
|
||||
tree := tview.NewTreeView()
|
||||
tree.
|
||||
SetBorder(true).
|
||||
SetTitle(a.db.Path())
|
||||
|
||||
var filters []handlers.Filter
|
||||
if cnr != nil {
|
||||
filters = append(filters, handlers.WithCID(*cnr))
|
||||
}
|
||||
if obj != nil {
|
||||
filters = append(filters, handlers.WithOID(*obj))
|
||||
}
|
||||
// var filters []handlers.Filter
|
||||
// if cnr != nil {
|
||||
// filters = append(filters, handlers.WithCID(*cnr))
|
||||
// }
|
||||
// if obj != nil {
|
||||
// filters = append(filters, handlers.WithOID(*obj))
|
||||
// }
|
||||
|
||||
handler := handlers.GetHandler(filters...)
|
||||
handler := schema.Start()
|
||||
|
||||
root := tview.NewTreeNode(".")
|
||||
root.
|
||||
|
@ -34,11 +34,11 @@ func (a *Application) newBucketsView(ctx context.Context, cnr *cid.ID, obj *oid.
|
|||
SetReference(&Bucket{nextHandler: handler})
|
||||
|
||||
var err error
|
||||
if len(filters) == 0 {
|
||||
err = a.getChildren(ctx, root, true)
|
||||
} else {
|
||||
err = a.getChildren(ctx, root, false)
|
||||
}
|
||||
// if len(filters) == 0 {
|
||||
err = a.getChildren(ctx, root, true)
|
||||
// } else {
|
||||
// err = a.getChildren(ctx, root, false)
|
||||
// }
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -90,17 +90,24 @@ func (a *Application) getChildren(ctx context.Context, parent *tview.TreeNode, l
|
|||
}
|
||||
|
||||
for bucket := range buffer {
|
||||
repr, next, err := handler(bucket.name, nil)
|
||||
if errors.Is(err, handlers.ErrFilter) {
|
||||
continue
|
||||
}
|
||||
res, err := handler(bucket.name, nil)
|
||||
// if errors.Is(err, handlers.ErrFilter) {
|
||||
// continue
|
||||
// }
|
||||
if err != nil {
|
||||
return err
|
||||
continue
|
||||
// return err
|
||||
}
|
||||
bucket.nextHandler = next
|
||||
bucket.result = repr
|
||||
bucket.nextHandler = res.Next
|
||||
bucket.result = res.Result
|
||||
|
||||
child := tview.NewTreeNode(repr.Key.String())
|
||||
var child *tview.TreeNode
|
||||
switch z := res.Result.(type) {
|
||||
case fmt.Stringer:
|
||||
child = tview.NewTreeNode(z.String())
|
||||
default:
|
||||
child = tview.NewTreeNode(fmt.Sprintf("%T", res.Result))
|
||||
}
|
||||
|
||||
child.SetSelectable(true)
|
||||
child.SetExpanded(false)
|
||||
|
@ -118,12 +125,13 @@ func (a *Application) getChildren(ctx context.Context, parent *tview.TreeNode, l
|
|||
|
||||
found := false
|
||||
for record := range records {
|
||||
_, _, err = next(record.key, record.value)
|
||||
if errors.Is(err, handlers.ErrFilter) {
|
||||
continue
|
||||
}
|
||||
_, err = res.Next(record.key, record.value)
|
||||
// if errors.Is(err, handlers.ErrFilter) {
|
||||
// continue
|
||||
// }
|
||||
if err != nil {
|
||||
return err
|
||||
continue
|
||||
// return err
|
||||
}
|
||||
found = true
|
||||
break
|
||||
|
|
|
@ -1,28 +1,21 @@
|
|||
package tuiutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
// func (a *Application) newDetailedView(_ context.Context, rec *Record) (tview.Primitive, error) {
|
||||
// view := tview.NewTextView()
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
// view.
|
||||
// SetText(rec.result.Val.DetailedString()).
|
||||
// SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
// if event.Key() == tcell.KeyBacktab {
|
||||
// a.nav.Pop()
|
||||
// return nil
|
||||
// }
|
||||
// return event
|
||||
// })
|
||||
|
||||
func (a *Application) newDetailedView(_ context.Context, rec *Record) (tview.Primitive, error) {
|
||||
view := tview.NewTextView()
|
||||
// view.
|
||||
// SetBorder(true).
|
||||
// SetTitle(rec.result.Key.String())
|
||||
|
||||
view.
|
||||
SetText(rec.result.Val.DetailedString()).
|
||||
SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
if event.Key() == tcell.KeyBacktab {
|
||||
a.nav.Pop()
|
||||
return nil
|
||||
}
|
||||
return event
|
||||
})
|
||||
|
||||
view.
|
||||
SetBorder(true).
|
||||
SetTitle(rec.result.Key.String())
|
||||
|
||||
return view, nil
|
||||
}
|
||||
// return view, nil
|
||||
// }
|
||||
|
|
|
@ -2,13 +2,10 @@ package tuiutil
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
handlers "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/schema"
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
@ -25,23 +22,24 @@ func (a *Application) newRecordsView(ctx context.Context, bkt *Bucket) (tview.Pr
|
|||
defer close(records)
|
||||
|
||||
for record := range temp {
|
||||
result, _, err := bkt.nextHandler(record.key, record.value)
|
||||
if errors.Is(err, handlers.ErrFilter) {
|
||||
continue
|
||||
}
|
||||
res, err := bkt.nextHandler(record.key, record.value)
|
||||
// if errors.Is(err, handlers.ErrFilter) {
|
||||
// continue
|
||||
// }
|
||||
if err != nil {
|
||||
a.stopOnErr(err)
|
||||
return
|
||||
continue
|
||||
// a.stopOnErr(err)
|
||||
// return
|
||||
}
|
||||
// record.nextHandler = next
|
||||
record.result = result
|
||||
record.result = res.Result
|
||||
records <- record
|
||||
}
|
||||
}()
|
||||
|
||||
box := tview.NewBox().
|
||||
SetBorder(true).
|
||||
SetTitle(bkt.result.Key.String())
|
||||
SetTitle(fmt.Sprintf("%T", bkt.result))
|
||||
|
||||
return &RecordsView{
|
||||
Box: box,
|
||||
|
@ -91,7 +89,6 @@ func (v *RecordsView) process() {
|
|||
if !ok {
|
||||
break
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, record.result.Key)
|
||||
v.records = append(v.records, record)
|
||||
}
|
||||
|
||||
|
@ -118,7 +115,7 @@ func (v *RecordsView) draw(screen tcell.Screen) {
|
|||
v.DrawForSubclass(screen, v)
|
||||
for index := v.firstRecordIndex; index < v.lastRecordIndex; index++ {
|
||||
result := v.records[index].result
|
||||
text := fmt.Sprintf("%s | %s", result.Key, result.Val)
|
||||
text := fmt.Sprintf("%s | %s", fmt.Sprintf("%T", result), "some val")
|
||||
if index == v.selectedRecordIndex {
|
||||
text = fmt.Sprintf("[:white]%s[:black]", text)
|
||||
}
|
||||
|
@ -134,7 +131,6 @@ func (v *RecordsView) Draw(screen tcell.Screen) {
|
|||
go func() {
|
||||
v.process()
|
||||
ready <- struct{}{}
|
||||
fmt.Fprintln(os.Stderr, "done")
|
||||
}()
|
||||
|
||||
select {
|
||||
|
@ -153,10 +149,8 @@ func (v *RecordsView) Draw(screen tcell.Screen) {
|
|||
_ = v.app.nav.Push(context.Background(), func(ctx context.Context) (tview.Primitive, error) {
|
||||
return loadingScreen.Start(ctx), nil
|
||||
})
|
||||
fmt.Fprintln(os.Stderr, "pushed")
|
||||
<-ready
|
||||
v.app.nav.Pop()
|
||||
fmt.Fprintln(os.Stderr, "pop")
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
@ -224,15 +218,15 @@ func (v *RecordsView) InputHandler() func(event *tcell.EventKey, _ func(p tview.
|
|||
v.moveToPrevPage()
|
||||
v.selectLastRecord()
|
||||
}
|
||||
case tcell.KeyTab:
|
||||
record := v.getSelectedItem()
|
||||
if record == nil {
|
||||
return
|
||||
}
|
||||
err := v.app.nav.Push(context.Background(), func(ctx context.Context) (tview.Primitive, error) {
|
||||
return v.app.newDetailedView(ctx, record)
|
||||
})
|
||||
v.app.stopOnErr(err)
|
||||
// case tcell.KeyTab:
|
||||
// record := v.getSelectedItem()
|
||||
// if record == nil {
|
||||
// return
|
||||
// }
|
||||
// err := v.app.nav.Push(context.Background(), func(ctx context.Context) (tview.Primitive, error) {
|
||||
// return v.app.newDetailedView(ctx, record)
|
||||
// })
|
||||
// v.app.stopOnErr(err)
|
||||
case tcell.KeyBacktab:
|
||||
v.app.nav.Pop()
|
||||
default:
|
||||
|
|
|
@ -1,515 +0,0 @@
|
|||
package schema
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/schema/parse"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/schema/parse/types"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
)
|
||||
|
||||
type KV struct {
|
||||
Key parse.Result
|
||||
Val parse.Result
|
||||
}
|
||||
|
||||
type Handler func(key, value []byte) (repr *KV, next Handler, err error)
|
||||
|
||||
func NewHandler(
|
||||
keyParser parse.Parser[parse.Result],
|
||||
valParser parse.Parser[parse.Result],
|
||||
next Handler,
|
||||
) Handler {
|
||||
return func(key, value []byte) (repr *KV, _ Handler, err error) {
|
||||
var keyRepr parse.Result = parse.NewRawResult("")
|
||||
var valueRepr parse.Result = parse.NewRawResult("")
|
||||
|
||||
if keyParser != nil {
|
||||
keyRepr, _, err = keyParser(key)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("can't parse key: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if valParser != nil {
|
||||
valueRepr, _, err = valParser(value)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("can't parse value: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return &KV{keyRepr, valueRepr}, next, nil
|
||||
}
|
||||
}
|
||||
|
||||
func Any(handlers ...Handler) Handler {
|
||||
return func(key, value []byte) (repr *KV, next Handler, err error) {
|
||||
var errs error
|
||||
for _, handler := range handlers {
|
||||
repr, next, err = handler(key, value)
|
||||
if err == nil {
|
||||
return repr, next, nil
|
||||
}
|
||||
errs = errors.Join(errs, err)
|
||||
}
|
||||
return nil, nil, errs
|
||||
}
|
||||
}
|
||||
|
||||
func WithFallback(handler Handler, fallback Handler) Handler {
|
||||
if handler == nil {
|
||||
return fallback
|
||||
}
|
||||
|
||||
return func(key, value []byte) (repr *KV, next Handler, err error) {
|
||||
repr, next, err = handler(key, value)
|
||||
if err == nil {
|
||||
return repr, WithFallback(next, fallback), nil
|
||||
}
|
||||
|
||||
repr, next, err = fallback(key, value)
|
||||
if err == nil {
|
||||
return repr, WithFallback(next, fallback), nil
|
||||
}
|
||||
|
||||
panic(fmt.Errorf("fallback handler returned an error: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
func ErrorHandler(handler Handler) Handler {
|
||||
if handler == nil {
|
||||
return nil
|
||||
}
|
||||
return func(key, value []byte) (repr *KV, next Handler, err error) {
|
||||
repr, next, err = handler(key, value)
|
||||
if err != nil {
|
||||
repr = &KV{
|
||||
Key: parse.NewRawResult(err.Error()),
|
||||
Val: parse.NewRawResult(""),
|
||||
}
|
||||
}
|
||||
return repr, ErrorHandler(next), nil
|
||||
}
|
||||
}
|
||||
|
||||
type Filter func(cfg *HandlerConfig)
|
||||
|
||||
type HandlerConfig struct {
|
||||
cidP parse.Parser[types.CID]
|
||||
oidP parse.Parser[types.OID]
|
||||
}
|
||||
|
||||
func GetHandler(filters ...Filter) Handler {
|
||||
cfg := &HandlerConfig{
|
||||
cidP: parse.CID,
|
||||
oidP: parse.OID,
|
||||
}
|
||||
|
||||
for _, filter := range filters {
|
||||
filter(cfg)
|
||||
}
|
||||
|
||||
handler := Any(
|
||||
GetInhumeBucketsHandler(cfg),
|
||||
GetContainerVolumeHandler(cfg),
|
||||
GetLockedBucketsHandler(cfg),
|
||||
GetShardInfoHandler(cfg),
|
||||
GetObjectBucketsHandler(cfg),
|
||||
GetSmallBucketsHandler(cfg),
|
||||
GetRootBucketsHandler(cfg),
|
||||
GetOwnerBucketsHandler(cfg),
|
||||
GetAttributeBucketsHandler(cfg),
|
||||
GetPayloadHashBucketHandler(cfg),
|
||||
GetParentBucketsHandler(cfg),
|
||||
GetSplitBucketsHandler(cfg),
|
||||
GetContainerCountersHandler(cfg),
|
||||
GetECInfoBucketHandler(cfg),
|
||||
)
|
||||
|
||||
if len(filters) > 0 {
|
||||
handler = FilterFailHandler(handler)
|
||||
} else {
|
||||
handler = WithFallback(handler, RawHandler)
|
||||
}
|
||||
|
||||
return handler
|
||||
}
|
||||
|
||||
func WithCID(id cid.ID) Filter {
|
||||
return func(cfg *HandlerConfig) {
|
||||
cfg.cidP = parse.Exact(parse.CID, types.CID{ID: id})
|
||||
}
|
||||
}
|
||||
|
||||
func WithOID(id oid.ID) Filter {
|
||||
return func(cfg *HandlerConfig) {
|
||||
cfg.oidP = parse.Exact(parse.OID, types.OID{ID: id})
|
||||
}
|
||||
}
|
||||
|
||||
func RawHandler(key, value []byte) (repr *KV, next Handler, err error) {
|
||||
return &KV{
|
||||
parse.NewRawResult(fmt.Sprintf("%v", key)),
|
||||
parse.NewRawResult(fmt.Sprintf("%v", value)),
|
||||
}, RawHandler, nil
|
||||
}
|
||||
|
||||
var ErrFilter = errors.New("it doesn't match the filter")
|
||||
|
||||
func FilterFailHandler(h Handler) Handler {
|
||||
return func(key, value []byte) (repr *KV, next Handler, err error) {
|
||||
repr, next, err = h(key, value)
|
||||
if err != nil {
|
||||
return nil, nil, ErrFilter
|
||||
}
|
||||
return repr, FilterFailHandler(next), nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetInhumeBucketsHandler(cfg *HandlerConfig) Handler {
|
||||
return NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Any(
|
||||
parse.Prefix(types.Graveyard),
|
||||
parse.Prefix(types.Garbage),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(cfg.cidP),
|
||||
parse.Finalize(cfg.oidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.Any(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.CID),
|
||||
parse.Finalize(parse.OID),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.Skip),
|
||||
)),
|
||||
nil,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func GetContainerVolumeHandler(cfg *HandlerConfig) Handler {
|
||||
return NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Prefix(types.ContainerVolume)),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(cfg.cidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Volume),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
nil,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func GetLockedBucketsHandler(cfg *HandlerConfig) Handler {
|
||||
return NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Prefix(types.Locked)),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(cfg.cidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(cfg.oidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.OIDsList),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
nil,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func GetShardInfoHandler(_ *HandlerConfig) Handler {
|
||||
return NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Prefix(types.ShardInfo)),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Map(
|
||||
parse.Any(
|
||||
parse.ExactString("id"),
|
||||
parse.ExactString("version"),
|
||||
parse.ExactString("logic_counter"),
|
||||
parse.ExactString("phy_counter"),
|
||||
parse.ExactString("user_counter"),
|
||||
),
|
||||
func(x string) parse.Result {
|
||||
return parse.NewRawResult(x, func(s string) string { return fmt.Sprintf("%13s", s) })
|
||||
},
|
||||
),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Map(
|
||||
parse.Uint64,
|
||||
func(x uint64) parse.Result { return parse.NewRawResult(strconv.FormatUint(x, 10)) },
|
||||
),
|
||||
nil,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func GetObjectBucketsHandler(cfg *HandlerConfig) Handler {
|
||||
return NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Any(
|
||||
parse.Prefix(types.Primary),
|
||||
parse.Prefix(types.Lockers),
|
||||
parse.Prefix(types.Tombstone),
|
||||
)),
|
||||
parse.Finalize(cfg.cidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(cfg.oidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Object),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
nil,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func GetSmallBucketsHandler(cfg *HandlerConfig) Handler {
|
||||
return NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Prefix(types.Small)),
|
||||
parse.Finalize(cfg.cidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(cfg.oidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.Any(
|
||||
parse.Finalize(parse.StorageID),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
nil,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func GetRootBucketsHandler(cfg *HandlerConfig) Handler {
|
||||
return NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Prefix(types.Root)),
|
||||
parse.Finalize(cfg.cidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(cfg.oidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.Any(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.SplitInfo),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
nil,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func GetAttributeBucketsHandler(cfg *HandlerConfig) Handler {
|
||||
return NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Prefix(types.UserAttribute)),
|
||||
parse.Finalize(cfg.cidP),
|
||||
parse.Finalize(parse.AttributeKey),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.AttributeValue),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(cfg.oidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.Skip),
|
||||
nil,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func GetOwnerBucketsHandler(cfg *HandlerConfig) Handler {
|
||||
return NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Prefix(types.Owner)),
|
||||
parse.Finalize(cfg.cidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.UID),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.Skip),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(cfg.oidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.Skip),
|
||||
nil,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func GetPayloadHashBucketHandler(cfg *HandlerConfig) Handler {
|
||||
return NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Prefix(types.PayloadHash)),
|
||||
parse.Finalize(cfg.cidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Checksum),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.OIDsList),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
nil,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func GetParentBucketsHandler(cfg *HandlerConfig) Handler {
|
||||
return NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Prefix(types.Parent)),
|
||||
parse.Finalize(cfg.cidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(cfg.oidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.OIDsList),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
nil,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func GetSplitBucketsHandler(cfg *HandlerConfig) Handler {
|
||||
return NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Prefix(types.Split)),
|
||||
parse.Finalize(cfg.cidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.UUID),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.OIDsList),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
nil,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func GetContainerCountersHandler(cfg *HandlerConfig) Handler {
|
||||
return NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Prefix(types.ContainerCounters)),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(cfg.cidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.ObjectCounters),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
nil,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func GetECInfoBucketHandler(cfg *HandlerConfig) Handler {
|
||||
return NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.Prefix(types.ECInfo)),
|
||||
parse.Finalize(cfg.cidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Finalize(parse.EOF),
|
||||
NewHandler(
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(cfg.oidP),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
parse.Collect(parse.Chain(
|
||||
parse.Finalize(parse.OIDsList),
|
||||
parse.Finalize(parse.EOF),
|
||||
)),
|
||||
nil,
|
||||
),
|
||||
)
|
||||
}
|
|
@ -1,280 +0,0 @@
|
|||
package parse
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/schema/parse/types"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
"github.com/google/uuid"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
type Parser[T any] func(data []byte) (result T, rest []byte, err error)
|
||||
|
||||
func Any[T any](parsers ...Parser[T]) Parser[T] {
|
||||
return func(data []byte) (result T, rest []byte, err error) {
|
||||
var zero T
|
||||
var errs error
|
||||
for _, parser := range parsers {
|
||||
result, rest, err = parser(data)
|
||||
if err == nil {
|
||||
return result, rest, nil
|
||||
}
|
||||
errs = errors.Join(errs, err)
|
||||
}
|
||||
return zero, data, errs
|
||||
}
|
||||
}
|
||||
|
||||
func Chain[T any](parsers ...Parser[T]) Parser[[]T] {
|
||||
return func(data []byte) (_ []T, rest []byte, err error) {
|
||||
var result T
|
||||
results := make([]T, len(parsers))
|
||||
|
||||
rest = data
|
||||
for index, parser := range parsers {
|
||||
result, rest, err = parser(rest)
|
||||
if err != nil {
|
||||
return nil, data, err
|
||||
}
|
||||
results[index] = result
|
||||
}
|
||||
return results, rest, nil
|
||||
}
|
||||
}
|
||||
|
||||
func Map[T, U any](parser Parser[T], f func(T) U) Parser[U] {
|
||||
return func(data []byte) (_ U, rest []byte, err error) {
|
||||
var zero U
|
||||
var result T
|
||||
|
||||
result, rest, err = parser(data)
|
||||
if err != nil {
|
||||
return zero, data, err
|
||||
}
|
||||
return f(result), rest, nil
|
||||
}
|
||||
}
|
||||
|
||||
func If[T any](parser Parser[T], predicate func(T) bool) Parser[T] {
|
||||
return func(data []byte) (result T, rest []byte, err error) {
|
||||
var zero T
|
||||
result, rest, err = parser(data)
|
||||
if err != nil {
|
||||
return zero, data, err
|
||||
}
|
||||
if !predicate(result) {
|
||||
return zero, data, errors.New("predicate returned false")
|
||||
}
|
||||
return result, rest, nil
|
||||
}
|
||||
}
|
||||
|
||||
func Exact[T comparable](parser Parser[T], value T) Parser[T] {
|
||||
return If(parser, func(v T) bool { return v == value })
|
||||
}
|
||||
|
||||
func Finalize[T fmt.Stringer](p Parser[T], formatters ...func(string) string) Parser[Result] {
|
||||
return func(data []byte) (result Result, rest []byte, err error) {
|
||||
var x T
|
||||
x, rest, err = p(data)
|
||||
if err != nil {
|
||||
return nil, data, err
|
||||
}
|
||||
return NewResultValue(x, formatters...), rest, nil
|
||||
}
|
||||
}
|
||||
|
||||
func Collect(parser Parser[[]Result]) Parser[Result] {
|
||||
return func(data []byte) (result Result, rest []byte, err error) {
|
||||
var results []Result
|
||||
results, rest, err = parser(data)
|
||||
if err != nil {
|
||||
return nil, data, err
|
||||
}
|
||||
return &ResultArray{results: results}, rest, nil
|
||||
}
|
||||
}
|
||||
|
||||
func Fail(data []byte) (result Result, rest []byte, err error) {
|
||||
return nil, data, errors.New("it's a parser that always fails")
|
||||
}
|
||||
|
||||
// func ExpectEOF[T any](parser Parser[T]) Parser[T] {
|
||||
// return func(data []byte) (result T, rest []byte, err error) {
|
||||
// var zero T
|
||||
// result, rest, err = parser(data)
|
||||
// if err != nil {
|
||||
// return zero, data, err
|
||||
// }
|
||||
// if len(rest) > 0 {
|
||||
// return zero, data, fmt.Errorf("expected EOF but got %v", rest)
|
||||
// }
|
||||
// return result, nil, nil
|
||||
// }
|
||||
// }
|
||||
|
||||
func Skip(_ []byte) (result types.Empty, rest []byte, err error) {
|
||||
return types.Empty{}, nil, nil
|
||||
}
|
||||
|
||||
func EOF(data []byte) (result types.Empty, rest []byte, err error) {
|
||||
if len(data) != 0 {
|
||||
return types.Empty{}, data, fmt.Errorf("expected EOF but got %v", data)
|
||||
}
|
||||
return types.Empty{}, nil, nil
|
||||
}
|
||||
|
||||
func Prefix(prefix types.Prefix) Parser[types.Prefix] {
|
||||
return func(data []byte) (result types.Prefix, rest []byte, err error) {
|
||||
var zero types.Prefix
|
||||
if len(data) == 0 {
|
||||
return zero, data, fmt.Errorf("expected prefix %d but got EOF", prefix)
|
||||
}
|
||||
if data[0] != byte(prefix) {
|
||||
return zero, data, fmt.Errorf("expected prefix %d but got %d", prefix, data[0])
|
||||
}
|
||||
return prefix, data[1:], nil
|
||||
}
|
||||
}
|
||||
|
||||
func CID(data []byte) (result types.CID, rest []byte, err error) {
|
||||
if len(data) < 32 {
|
||||
return types.CID{}, data, errors.New("can't parse CID, not enough data")
|
||||
}
|
||||
id := cid.ID{}
|
||||
err = id.Decode(data[:32])
|
||||
if err != nil {
|
||||
return types.CID{}, data, fmt.Errorf("can't parse CID: %w", err)
|
||||
}
|
||||
return types.CID{ID: id}, data[32:], nil
|
||||
}
|
||||
|
||||
func OID(data []byte) (result types.OID, rest []byte, err error) {
|
||||
if len(data) < 32 {
|
||||
return types.OID{}, data, errors.New("can't parse OID, not enough data")
|
||||
}
|
||||
id := oid.ID{}
|
||||
err = id.Decode(data[:32])
|
||||
if err != nil {
|
||||
return types.OID{}, data, fmt.Errorf("can't parse OID: %w", err)
|
||||
}
|
||||
return types.OID{ID: id}, data[32:], nil
|
||||
}
|
||||
|
||||
func UID(data []byte) (result types.UID, rest []byte, err error) {
|
||||
id := user.ID{}
|
||||
if err = id.DecodeString(string(data)); err != nil {
|
||||
return types.UID{}, data, fmt.Errorf("can't parse UID: %w", err)
|
||||
}
|
||||
return types.UID{ID: id}, nil, nil
|
||||
}
|
||||
|
||||
func Object(data []byte) (result types.Object, rest []byte, err error) {
|
||||
obj := objectSDK.New()
|
||||
if err = obj.Unmarshal(data); err != nil {
|
||||
return types.Object{}, data, fmt.Errorf("can't parse object: %w", err)
|
||||
}
|
||||
return types.Object{Obj: obj}, nil, nil
|
||||
}
|
||||
|
||||
func Uint64(data []byte) (result uint64, rest []byte, err error) {
|
||||
if len(data) < 8 {
|
||||
return 0, data, errors.New("can't parse uint64, not enough data")
|
||||
}
|
||||
return binary.LittleEndian.Uint64(data[:8]), data[8:], nil
|
||||
}
|
||||
|
||||
func String(data []byte) (result string, rest []byte, err error) {
|
||||
if len(data) == 0 {
|
||||
return "", data, errors.New("can't parse string, unexpected EOF")
|
||||
}
|
||||
return string(data), nil, nil
|
||||
}
|
||||
|
||||
func Checksum(data []byte) (result types.Checksum, next []byte, err error) {
|
||||
if len(data) < 32 {
|
||||
return types.Checksum{}, data, errors.New("can't parse checksum, not enough data")
|
||||
}
|
||||
return types.Checksum{Value: data[:32]}, data[32:], nil
|
||||
}
|
||||
|
||||
func OIDsList(data []byte) (result types.OIDsList, rest []byte, err error) {
|
||||
r := io.NewBinReaderFromBuf(data)
|
||||
|
||||
size := r.ReadVarUint()
|
||||
oids := make([]types.OID, size)
|
||||
|
||||
var i uint64
|
||||
for ; i < size; i++ {
|
||||
id := oid.ID{}
|
||||
if err = id.Decode(r.ReadVarBytes()); err != nil {
|
||||
return types.OIDsList{}, data, fmt.Errorf("can't parse list of OIDs: %w", err)
|
||||
}
|
||||
oids[i] = types.OID{ID: id}
|
||||
}
|
||||
return types.OIDsList{OIDs: oids}, nil, nil
|
||||
}
|
||||
|
||||
func UUID(data []byte) (result types.UUID, rest []byte, err error) {
|
||||
if len(data) < 16 {
|
||||
return types.UUID{}, data, errors.New("can't parse UUID, not enough data")
|
||||
}
|
||||
|
||||
id := uuid.UUID{}
|
||||
if err := id.UnmarshalBinary(data[:16]); err != nil {
|
||||
return types.UUID{}, data, fmt.Errorf("can't parsse UUID: %w", err)
|
||||
}
|
||||
return types.UUID{ID: id}, data[16:], nil
|
||||
}
|
||||
|
||||
func SplitInfo(data []byte) (result types.SplitInfo, rest []byte, err error) {
|
||||
info := objectSDK.NewSplitInfo()
|
||||
if err = info.Unmarshal(data); err != nil {
|
||||
return types.SplitInfo{}, data, fmt.Errorf("can't parse split info: %w", err)
|
||||
}
|
||||
return types.SplitInfo{Info: info}, nil, nil
|
||||
}
|
||||
|
||||
var AttributeKey = Map(String, func(s string) types.AttributeKey {
|
||||
return types.AttributeKey{Key: s}
|
||||
})
|
||||
|
||||
var AttributeValue = Map(String, func(s string) types.AttributeValue {
|
||||
return types.AttributeValue{Value: s}
|
||||
})
|
||||
|
||||
var StorageID = Map(String, func(x string) types.StorageID {
|
||||
return types.StorageID{Path: x}
|
||||
})
|
||||
|
||||
var Volume = Map(Uint64, func(x uint64) types.Volume {
|
||||
return types.Volume{Volume: x}
|
||||
})
|
||||
|
||||
var ObjectCounters = Map(
|
||||
Chain(Uint64, Uint64, Uint64),
|
||||
func(x []uint64) types.ObjectCounters {
|
||||
return types.ObjectCounters{
|
||||
Logical: x[0],
|
||||
Physical: x[1],
|
||||
User: x[2],
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
func ExactString(s string) Parser[string] {
|
||||
return func(data []byte) (result string, rest []byte, err error) {
|
||||
rest, found := bytes.CutPrefix(data, []byte(s))
|
||||
if !found {
|
||||
return "", data, fmt.Errorf("can't parse string %s, string not found", s)
|
||||
}
|
||||
return s, rest, nil
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
package parse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
type Result interface {
|
||||
fmt.Stringer
|
||||
DetailedString() string
|
||||
}
|
||||
|
||||
type ResultValue struct {
|
||||
value fmt.Stringer
|
||||
formatters []func(string) string
|
||||
}
|
||||
|
||||
func NewResultValue(value fmt.Stringer, formatters ...func(string) string) *ResultValue {
|
||||
return &ResultValue{
|
||||
value: value,
|
||||
formatters: formatters,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ResultValue) String() string {
|
||||
s := r.value.String()
|
||||
for _, f := range r.formatters {
|
||||
s = f(s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (r *ResultValue) DetailedString() string {
|
||||
return spew.Sdump(r.value)
|
||||
}
|
||||
|
||||
type ResultArray struct {
|
||||
results []Result
|
||||
}
|
||||
|
||||
func NewResultArray(results ...Result) *ResultArray {
|
||||
return &ResultArray{results}
|
||||
}
|
||||
|
||||
func (r *ResultArray) String() string {
|
||||
b := strings.Builder{}
|
||||
for _, result := range r.results {
|
||||
_, _ = b.WriteString(result.String())
|
||||
_, _ = b.WriteString(" ")
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (r *ResultArray) DetailedString() string {
|
||||
b := strings.Builder{}
|
||||
for _, result := range r.results {
|
||||
_, _ = b.WriteString(result.DetailedString())
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
type RawResult struct {
|
||||
s string
|
||||
formatters []func(string) string
|
||||
}
|
||||
|
||||
func NewRawResult(s string, formatters ...func(string) string) *RawResult {
|
||||
return &RawResult{s: s, formatters: formatters}
|
||||
}
|
||||
|
||||
func (r *RawResult) String() string {
|
||||
s := r.s
|
||||
for _, f := range r.formatters {
|
||||
s = f(s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (r *RawResult) DetailedString() string {
|
||||
s := r.s
|
||||
for _, f := range r.formatters {
|
||||
s = f(s)
|
||||
}
|
||||
return s + "\n"
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package types
|
||||
|
||||
type AttributeKey struct {
|
||||
Key string
|
||||
}
|
||||
|
||||
func (k AttributeKey) String() string {
|
||||
return k.Key
|
||||
}
|
||||
|
||||
type AttributeValue struct {
|
||||
Value string
|
||||
}
|
||||
|
||||
func (v AttributeValue) String() string {
|
||||
return v.Value
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
type Checksum struct {
|
||||
Value []byte
|
||||
}
|
||||
|
||||
func (cs Checksum) String() string {
|
||||
return hex.EncodeToString(cs.Value)
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type ObjectCounters struct {
|
||||
Logical uint64
|
||||
Physical uint64
|
||||
User uint64
|
||||
}
|
||||
|
||||
func (c ObjectCounters) String() string {
|
||||
return fmt.Sprintf(
|
||||
"logical %d, physical %d, user %d",
|
||||
c.Logical, c.Physical, c.User,
|
||||
)
|
||||
}
|
||||
|
||||
type Volume struct {
|
||||
Volume uint64
|
||||
}
|
||||
|
||||
func (v Volume) String() string {
|
||||
return strconv.FormatUint(v.Volume, 10)
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package types
|
||||
|
||||
type Empty struct{}
|
||||
|
||||
func (e Empty) String() string {
|
||||
return ""
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type CID struct {
|
||||
ID cid.ID
|
||||
}
|
||||
|
||||
func (id CID) String() string {
|
||||
return fmt.Sprintf("CID [red]%-44s[white]", id.ID)
|
||||
}
|
||||
|
||||
type OID struct {
|
||||
ID oid.ID
|
||||
}
|
||||
|
||||
func (id OID) String() string {
|
||||
return fmt.Sprintf("OID [red]%-44s[white]", id.ID)
|
||||
}
|
||||
|
||||
type UID struct {
|
||||
ID user.ID
|
||||
}
|
||||
|
||||
func (id UID) String() string {
|
||||
return id.ID.String()
|
||||
}
|
||||
|
||||
type OIDsList struct {
|
||||
OIDs []OID
|
||||
}
|
||||
|
||||
func (l OIDsList) String() string {
|
||||
var acc []string
|
||||
for _, id := range l.OIDs {
|
||||
acc = append(acc, id.String())
|
||||
}
|
||||
return strings.TrimRight(strings.Join(acc, " "), " ")
|
||||
}
|
||||
|
||||
type UUID struct {
|
||||
ID uuid.UUID
|
||||
}
|
||||
|
||||
func (id UUID) String() string {
|
||||
return id.ID.String()
|
||||
}
|
||||
|
||||
type StorageID struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
func (id StorageID) String() string {
|
||||
return id.Path
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
)
|
||||
|
||||
type (
|
||||
Object struct {
|
||||
Obj *objectSDK.Object
|
||||
}
|
||||
|
||||
SplitInfo struct {
|
||||
Info *objectSDK.SplitInfo
|
||||
}
|
||||
)
|
||||
|
||||
func (o Object) String() string {
|
||||
return fmt.Sprintf("%+v", o.Obj)
|
||||
}
|
||||
|
||||
func (si SplitInfo) String() string {
|
||||
return fmt.Sprintf("%+v", si.Info)
|
||||
}
|
Loading…
Reference in a new issue