diff --git a/datastore.go b/datastore.go index 0d075df..8926bb4 100644 --- a/datastore.go +++ b/datastore.go @@ -4,7 +4,6 @@ import ( "context" "errors" "io" - "time" query "github.com/ipfs/go-datastore/query" ) @@ -103,8 +102,7 @@ type Read interface { // capabilities of a `Batch`, but the reverse is NOT true. type Batching interface { Datastore - - Batch(ctx context.Context) (Batch, error) + BatchingFeature } // ErrBatchUnsupported is returned if the by Batch if the Datastore doesn't @@ -115,8 +113,7 @@ var ErrBatchUnsupported = errors.New("this datastore does not support batching") // which may need checking on-disk data integrity. type CheckedDatastore interface { Datastore - - Check(ctx context.Context) error + CheckedFeature } // ScrubbedDatastore is an interface that should be implemented by datastores @@ -124,25 +121,21 @@ type CheckedDatastore interface { // error correction. type ScrubbedDatastore interface { Datastore - - Scrub(ctx context.Context) error + ScrubbedFeature } // GCDatastore is an interface that should be implemented by datastores which // don't free disk space by just removing data from them. type GCDatastore interface { Datastore - - CollectGarbage(ctx context.Context) error + GCFeature } // PersistentDatastore is an interface that should be implemented by datastores // which can report disk usage. type PersistentDatastore interface { Datastore - - // DiskUsage returns the space used by a datastore, in bytes. - DiskUsage(ctx context.Context) (uint64, error) + PersistentFeature } // DiskUsage checks if a Datastore is a @@ -163,13 +156,6 @@ type TTLDatastore interface { TTL } -// TTL encapulates the methods that deal with entries with time-to-live. -type TTL interface { - PutWithTTL(ctx context.Context, key Key, value []byte, ttl time.Duration) error - SetTTL(ctx context.Context, key Key, ttl time.Duration) error - GetExpiration(ctx context.Context, key Key) (time.Time, error) -} - // Txn extends the Datastore type. Txns allow users to batch queries and // mutations to the Datastore into atomic groups, or transactions. Actions // performed on a transaction will not take hold until a successful call to @@ -194,8 +180,7 @@ type Txn interface { // support transactions. type TxnDatastore interface { Datastore - - NewTransaction(ctx context.Context, readOnly bool) (Txn, error) + TxnFeature } // Errors diff --git a/features.go b/features.go new file mode 100644 index 0000000..5350c05 --- /dev/null +++ b/features.go @@ -0,0 +1,142 @@ +package datastore + +import ( + "context" + "reflect" + "time" +) + +const ( + FeatureNameBatching = "Batching" + FeatureNameChecked = "Checked" + FeatureNameGC = "GC" + FeatureNamePersistent = "Persistent" + FeatureNameScrubbed = "Scrubbed" + FeatureNameTTL = "TTL" + FeatureNameTransaction = "Transaction" +) + +type BatchingFeature interface { + Batch(ctx context.Context) (Batch, error) +} + +type CheckedFeature interface { + Check(ctx context.Context) error +} + +type ScrubbedFeature interface { + Scrub(ctx context.Context) error +} + +type GCFeature interface { + CollectGarbage(ctx context.Context) error +} + +type PersistentFeature interface { + // DiskUsage returns the space used by a datastore, in bytes. + DiskUsage(ctx context.Context) (uint64, error) +} + +// TTL encapulates the methods that deal with entries with time-to-live. +type TTL interface { + PutWithTTL(ctx context.Context, key Key, value []byte, ttl time.Duration) error + SetTTL(ctx context.Context, key Key, ttl time.Duration) error + GetExpiration(ctx context.Context, key Key) (time.Time, error) +} + +type TxnFeature interface { + NewTransaction(ctx context.Context, readOnly bool) (Txn, error) +} + +// Feature contains metadata about a datastore Feature. +type Feature struct { + Name string + // Interface is the nil interface of the feature. + Interface interface{} + // DatastoreInterface is the nil interface of the feature's corresponding datastore interface. + DatastoreInterface interface{} +} + +var featuresByName map[string]Feature + +func init() { + featuresByName = map[string]Feature{} + for _, f := range Features() { + featuresByName[f.Name] = f + } +} + +// Features returns a list of all known datastore features. +// This serves both to provide an authoritative list of features, +// and to define a canonical ordering of features. +func Features() []Feature { + // for backwards compatibility, only append to this list + return []Feature{ + { + Name: FeatureNameBatching, + Interface: (*BatchingFeature)(nil), + DatastoreInterface: (*Batching)(nil), + }, + { + Name: FeatureNameChecked, + Interface: (*CheckedFeature)(nil), + DatastoreInterface: (*CheckedDatastore)(nil), + }, + { + Name: FeatureNameGC, + Interface: (*GCFeature)(nil), + DatastoreInterface: (*GCDatastore)(nil), + }, + { + Name: FeatureNamePersistent, + Interface: (*PersistentFeature)(nil), + DatastoreInterface: (*PersistentDatastore)(nil), + }, + { + Name: FeatureNameScrubbed, + Interface: (*ScrubbedFeature)(nil), + DatastoreInterface: (*ScrubbedDatastore)(nil), + }, + { + Name: FeatureNameTTL, + Interface: (*TTL)(nil), + DatastoreInterface: (*TTLDatastore)(nil), + }, + { + Name: FeatureNameTransaction, + Interface: (*TxnFeature)(nil), + DatastoreInterface: (*TxnDatastore)(nil), + }, + } +} + +// FeaturesByNames returns the features with the given names, if they are known. +func FeaturesByNames(names ...string) (features []Feature) { + for _, n := range names { + if feat, ok := featuresByName[n]; ok { + features = append(features, feat) + } + } + return +} + +// FeatureByName returns the feature with the given name, if known. +func FeatureByName(name string) (Feature, bool) { + feat, known := featuresByName[name] + return feat, known +} + +// FeaturesForDatastore returns the features supported by the given datastore. +func FeaturesForDatastore(dstore Datastore) (features []Feature) { + if dstore == nil { + return nil + } + dstoreType := reflect.ValueOf(dstore).Type() + for _, f := range Features() { + fType := reflect.TypeOf(f.Interface).Elem() + if dstoreType.Implements(fType) { + features = append(features, f) + } + } + return +} diff --git a/features_test.go b/features_test.go new file mode 100644 index 0000000..2741fce --- /dev/null +++ b/features_test.go @@ -0,0 +1,80 @@ +package datastore + +import ( + "reflect" + "testing" +) + +func TestFeaturesByNames(t *testing.T) { + feats := FeaturesByNames() + if feats != nil { + t.Fatalf("expected nil features, got %v", feats) + } + + feats = FeaturesByNames(FeatureNameBatching) + if len(feats) != 1 || + feats[0].Name != FeatureNameBatching || + feats[0].Interface != (*BatchingFeature)(nil) || + feats[0].DatastoreInterface != (*Batching)(nil) { + t.Fatalf("expected a batching feature, got %v", feats) + } + + feats = FeaturesByNames(FeatureNameBatching, "UnknownFeature") + if len(feats) != 1 || feats[0].Name != FeatureNameBatching { + t.Fatalf("expected a batching feature, got %v", feats) + } +} + +func TestFeatureByName(t *testing.T) { + feat, ok := FeatureByName(FeatureNameBatching) + if !ok { + t.Fatalf("expected a batching feature") + } + if feat.Name != FeatureNameBatching || + feat.Interface != (*BatchingFeature)(nil) || + feat.DatastoreInterface != (*Batching)(nil) { + t.Fatalf("expected a batching feature, got %v", feat) + } + + feat, ok = FeatureByName("UnknownFeature") + if ok { + t.Fatalf("expected UnknownFeature not to be found") + } +} + +func TestFeaturesForDatastore(t *testing.T) { + cases := []struct { + name string + d Datastore + expectedFeatures []string + }{ + { + name: "MapDatastore", + d: &MapDatastore{}, + expectedFeatures: []string{"Batching"}, + }, + { + name: "NullDatastore", + d: &NullDatastore{}, + expectedFeatures: []string{"Batching"}, + }, + { + name: "LogDatastore", + d: &LogDatastore{}, + expectedFeatures: []string{"Batching", "Checked", "GC", "Persistent", "Scrubbed"}, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + feats := FeaturesForDatastore(c.d) + if len(feats) != len(c.expectedFeatures) { + t.Fatalf("expected %d features, got %v", len(c.expectedFeatures), feats) + } + expectedFeats := FeaturesByNames(c.expectedFeatures...) + if !reflect.DeepEqual(expectedFeats, feats) { + t.Fatalf("expected features %v, got %v", c.expectedFeatures, feats) + } + }) + } +} diff --git a/scoped/doc.go b/scoped/doc.go new file mode 100644 index 0000000..12afef7 --- /dev/null +++ b/scoped/doc.go @@ -0,0 +1,40 @@ +// Package scoped introduces a Datastore Shim that scopes down a source datastore +// to the features supported by a target datastore. This is useful e.g. for dispatching +// datastores, where the dispatcher needs to dynamically implement the same features +// as the dispatchee, without knowing them statically. +// +// Use the Wrap function to wrap a datastore so that its interface is scoped down to +// only those features supported both by it and its target datastore. Note that this +// is a set intersection--if the target implements a feature not supported by the +// wrapped datastore, then the resulting shim will not implement them either. +// +// For example: +// +// import ( +// "context" +// scopedds "github.com/ipfs/go-datastore/scoped" +// ds "github.com/ipfs/go-datastore" +// ) +// +// type BatchingDS struct { ds.Datastore } +// +// func (b *BatchingDS) Batch(ctx context.Context) (ds.Batch, error) { +// // custom batching +// return nil, nil +// } +// +// type BoringDS struct { ds.Datastore } +// +// func Dispatcher(dstore ds.Datastore) ds.Datastore { +// dispatcher := &BatchingDS{Datastore: dstore} +// dispatchee := &BoringDS{Datastore: dstore} +// +// // the dispatcher supports batching, but since the dispatchee +// // doesn't, the returned dispatcher does NOT implement ds.Batching +// +// return scoped.Wrap(dispatcher, dispatchee) +// } + +package scoped + +//go:generate go run generate/main.go diff --git a/scoped/generate/main.go b/scoped/generate/main.go new file mode 100644 index 0000000..d823914 --- /dev/null +++ b/scoped/generate/main.go @@ -0,0 +1,102 @@ +//go:build generate +// +build generate + +package main + +import ( + "bytes" + "go/format" + "math" + "os" + "reflect" + "text/template" + + ds "github.com/ipfs/go-datastore" +) + +var tmpl = template.Must(template.New("").Parse(`// Code generated by go generate; DO NOT EDIT. + +package scoped + +import ( + ds "github.com/ipfs/go-datastore" +) + +{{ range $idx, $features := .StructFeatures -}} +type ds{{ $idx }} struct { + ds.Datastore + {{- range $feat := $features }} + ds.{{ $feat.IFace }} + {{- end }} +} +func (d *ds{{ $idx }}) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} +{{ end }} +var ctors = map[int]func(ds.Datastore) ds.Datastore{ + {{- range $idx, $features := .StructFeatures }} + {{ $idx }}: func(dstore ds.Datastore) ds.Datastore { + return &ds{{ $idx }}{ + Datastore: dstore, + {{- range $feat := $features }} + {{ $feat.IFace }}: dstore.(ds.{{ $feat.DatastoreIFace }}), + {{- end }} + } + }, + {{- end }} +} +`)) + +func main() { + type feat struct { + IFace string + DatastoreIFace string + } + + type templateData struct { + StructFeatures [][]feat + Features []feat + } + + tmplData := templateData{} + features := ds.Features() + + for _, f := range features { + tmplData.Features = append(tmplData.Features, feat{ + IFace: reflect.TypeOf(f.Interface).Elem().Name(), + DatastoreIFace: reflect.TypeOf(f.DatastoreInterface).Elem().Name(), + }) + } + + numStructs := int(math.Pow(2, float64(len(features)))) + tmplData.StructFeatures = make([][]feat, numStructs) + for i := 0; i < numStructs; i++ { + for bit := 0; bit < len(features); bit++ { + if ((i >> bit) & 1) == 1 { + tmplData.StructFeatures[i] = append(tmplData.StructFeatures[i], tmplData.Features[bit]) + } + } + } + + buf := bytes.Buffer{} + err := tmpl.Execute(&buf, tmplData) + if err != nil { + panic(err) + } + + b, err := format.Source(buf.Bytes()) + if err != nil { + panic(err) + } + + f, err := os.Create("impls.go") + if err != nil { + panic(err) + } + defer f.Close() + + _, err = f.Write(b) + if err != nil { + panic(err) + } +} diff --git a/scoped/impls.go b/scoped/impls.go new file mode 100644 index 0000000..00616a2 --- /dev/null +++ b/scoped/impls.go @@ -0,0 +1,2570 @@ +// Code generated by go generate; DO NOT EDIT. + +package scoped + +import ( + ds "github.com/ipfs/go-datastore" +) + +type ds0 struct { + ds.Datastore +} + +func (d *ds0) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds1 struct { + ds.Datastore + ds.BatchingFeature +} + +func (d *ds1) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds2 struct { + ds.Datastore + ds.CheckedFeature +} + +func (d *ds2) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds3 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature +} + +func (d *ds3) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds4 struct { + ds.Datastore + ds.GCFeature +} + +func (d *ds4) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds5 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature +} + +func (d *ds5) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds6 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature +} + +func (d *ds6) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds7 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature +} + +func (d *ds7) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds8 struct { + ds.Datastore + ds.PersistentFeature +} + +func (d *ds8) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds9 struct { + ds.Datastore + ds.BatchingFeature + ds.PersistentFeature +} + +func (d *ds9) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds10 struct { + ds.Datastore + ds.CheckedFeature + ds.PersistentFeature +} + +func (d *ds10) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds11 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.PersistentFeature +} + +func (d *ds11) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds12 struct { + ds.Datastore + ds.GCFeature + ds.PersistentFeature +} + +func (d *ds12) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds13 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature + ds.PersistentFeature +} + +func (d *ds13) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds14 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature +} + +func (d *ds14) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds15 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature +} + +func (d *ds15) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds16 struct { + ds.Datastore + ds.ScrubbedFeature +} + +func (d *ds16) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds17 struct { + ds.Datastore + ds.BatchingFeature + ds.ScrubbedFeature +} + +func (d *ds17) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds18 struct { + ds.Datastore + ds.CheckedFeature + ds.ScrubbedFeature +} + +func (d *ds18) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds19 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.ScrubbedFeature +} + +func (d *ds19) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds20 struct { + ds.Datastore + ds.GCFeature + ds.ScrubbedFeature +} + +func (d *ds20) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds21 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature + ds.ScrubbedFeature +} + +func (d *ds21) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds22 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature + ds.ScrubbedFeature +} + +func (d *ds22) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds23 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature + ds.ScrubbedFeature +} + +func (d *ds23) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds24 struct { + ds.Datastore + ds.PersistentFeature + ds.ScrubbedFeature +} + +func (d *ds24) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds25 struct { + ds.Datastore + ds.BatchingFeature + ds.PersistentFeature + ds.ScrubbedFeature +} + +func (d *ds25) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds26 struct { + ds.Datastore + ds.CheckedFeature + ds.PersistentFeature + ds.ScrubbedFeature +} + +func (d *ds26) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds27 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.PersistentFeature + ds.ScrubbedFeature +} + +func (d *ds27) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds28 struct { + ds.Datastore + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature +} + +func (d *ds28) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds29 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature +} + +func (d *ds29) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds30 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature +} + +func (d *ds30) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds31 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature +} + +func (d *ds31) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds32 struct { + ds.Datastore + ds.TTL +} + +func (d *ds32) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds33 struct { + ds.Datastore + ds.BatchingFeature + ds.TTL +} + +func (d *ds33) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds34 struct { + ds.Datastore + ds.CheckedFeature + ds.TTL +} + +func (d *ds34) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds35 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.TTL +} + +func (d *ds35) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds36 struct { + ds.Datastore + ds.GCFeature + ds.TTL +} + +func (d *ds36) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds37 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature + ds.TTL +} + +func (d *ds37) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds38 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature + ds.TTL +} + +func (d *ds38) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds39 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature + ds.TTL +} + +func (d *ds39) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds40 struct { + ds.Datastore + ds.PersistentFeature + ds.TTL +} + +func (d *ds40) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds41 struct { + ds.Datastore + ds.BatchingFeature + ds.PersistentFeature + ds.TTL +} + +func (d *ds41) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds42 struct { + ds.Datastore + ds.CheckedFeature + ds.PersistentFeature + ds.TTL +} + +func (d *ds42) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds43 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.PersistentFeature + ds.TTL +} + +func (d *ds43) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds44 struct { + ds.Datastore + ds.GCFeature + ds.PersistentFeature + ds.TTL +} + +func (d *ds44) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds45 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature + ds.PersistentFeature + ds.TTL +} + +func (d *ds45) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds46 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature + ds.TTL +} + +func (d *ds46) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds47 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature + ds.TTL +} + +func (d *ds47) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds48 struct { + ds.Datastore + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds48) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds49 struct { + ds.Datastore + ds.BatchingFeature + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds49) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds50 struct { + ds.Datastore + ds.CheckedFeature + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds50) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds51 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds51) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds52 struct { + ds.Datastore + ds.GCFeature + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds52) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds53 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds53) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds54 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds54) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds55 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds55) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds56 struct { + ds.Datastore + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds56) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds57 struct { + ds.Datastore + ds.BatchingFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds57) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds58 struct { + ds.Datastore + ds.CheckedFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds58) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds59 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds59) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds60 struct { + ds.Datastore + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds60) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds61 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds61) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds62 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds62) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds63 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL +} + +func (d *ds63) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds64 struct { + ds.Datastore + ds.TxnFeature +} + +func (d *ds64) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds65 struct { + ds.Datastore + ds.BatchingFeature + ds.TxnFeature +} + +func (d *ds65) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds66 struct { + ds.Datastore + ds.CheckedFeature + ds.TxnFeature +} + +func (d *ds66) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds67 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.TxnFeature +} + +func (d *ds67) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds68 struct { + ds.Datastore + ds.GCFeature + ds.TxnFeature +} + +func (d *ds68) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds69 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature + ds.TxnFeature +} + +func (d *ds69) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds70 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature + ds.TxnFeature +} + +func (d *ds70) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds71 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature + ds.TxnFeature +} + +func (d *ds71) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds72 struct { + ds.Datastore + ds.PersistentFeature + ds.TxnFeature +} + +func (d *ds72) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds73 struct { + ds.Datastore + ds.BatchingFeature + ds.PersistentFeature + ds.TxnFeature +} + +func (d *ds73) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds74 struct { + ds.Datastore + ds.CheckedFeature + ds.PersistentFeature + ds.TxnFeature +} + +func (d *ds74) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds75 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.PersistentFeature + ds.TxnFeature +} + +func (d *ds75) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds76 struct { + ds.Datastore + ds.GCFeature + ds.PersistentFeature + ds.TxnFeature +} + +func (d *ds76) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds77 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature + ds.PersistentFeature + ds.TxnFeature +} + +func (d *ds77) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds78 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature + ds.TxnFeature +} + +func (d *ds78) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds79 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature + ds.TxnFeature +} + +func (d *ds79) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds80 struct { + ds.Datastore + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds80) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds81 struct { + ds.Datastore + ds.BatchingFeature + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds81) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds82 struct { + ds.Datastore + ds.CheckedFeature + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds82) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds83 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds83) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds84 struct { + ds.Datastore + ds.GCFeature + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds84) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds85 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds85) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds86 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds86) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds87 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds87) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds88 struct { + ds.Datastore + ds.PersistentFeature + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds88) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds89 struct { + ds.Datastore + ds.BatchingFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds89) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds90 struct { + ds.Datastore + ds.CheckedFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds90) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds91 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds91) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds92 struct { + ds.Datastore + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds92) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds93 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds93) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds94 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds94) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds95 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TxnFeature +} + +func (d *ds95) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds96 struct { + ds.Datastore + ds.TTL + ds.TxnFeature +} + +func (d *ds96) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds97 struct { + ds.Datastore + ds.BatchingFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds97) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds98 struct { + ds.Datastore + ds.CheckedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds98) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds99 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds99) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds100 struct { + ds.Datastore + ds.GCFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds100) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds101 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds101) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds102 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds102) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds103 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds103) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds104 struct { + ds.Datastore + ds.PersistentFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds104) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds105 struct { + ds.Datastore + ds.BatchingFeature + ds.PersistentFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds105) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds106 struct { + ds.Datastore + ds.CheckedFeature + ds.PersistentFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds106) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds107 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.PersistentFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds107) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds108 struct { + ds.Datastore + ds.GCFeature + ds.PersistentFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds108) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds109 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature + ds.PersistentFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds109) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds110 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds110) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds111 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds111) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds112 struct { + ds.Datastore + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds112) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds113 struct { + ds.Datastore + ds.BatchingFeature + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds113) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds114 struct { + ds.Datastore + ds.CheckedFeature + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds114) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds115 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds115) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds116 struct { + ds.Datastore + ds.GCFeature + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds116) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds117 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds117) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds118 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds118) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds119 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds119) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds120 struct { + ds.Datastore + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds120) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds121 struct { + ds.Datastore + ds.BatchingFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds121) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds122 struct { + ds.Datastore + ds.CheckedFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds122) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds123 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds123) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds124 struct { + ds.Datastore + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds124) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds125 struct { + ds.Datastore + ds.BatchingFeature + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds125) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds126 struct { + ds.Datastore + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds126) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +type ds127 struct { + ds.Datastore + ds.BatchingFeature + ds.CheckedFeature + ds.GCFeature + ds.PersistentFeature + ds.ScrubbedFeature + ds.TTL + ds.TxnFeature +} + +func (d *ds127) Children() []ds.Datastore { + return []ds.Datastore{d.Datastore} +} + +var ctors = map[int]func(ds.Datastore) ds.Datastore{ + 0: func(dstore ds.Datastore) ds.Datastore { + return &ds0{ + Datastore: dstore, + } + }, + 1: func(dstore ds.Datastore) ds.Datastore { + return &ds1{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + } + }, + 2: func(dstore ds.Datastore) ds.Datastore { + return &ds2{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + } + }, + 3: func(dstore ds.Datastore) ds.Datastore { + return &ds3{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + } + }, + 4: func(dstore ds.Datastore) ds.Datastore { + return &ds4{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + } + }, + 5: func(dstore ds.Datastore) ds.Datastore { + return &ds5{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + } + }, + 6: func(dstore ds.Datastore) ds.Datastore { + return &ds6{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + } + }, + 7: func(dstore ds.Datastore) ds.Datastore { + return &ds7{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + } + }, + 8: func(dstore ds.Datastore) ds.Datastore { + return &ds8{ + Datastore: dstore, + PersistentFeature: dstore.(ds.PersistentDatastore), + } + }, + 9: func(dstore ds.Datastore) ds.Datastore { + return &ds9{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + PersistentFeature: dstore.(ds.PersistentDatastore), + } + }, + 10: func(dstore ds.Datastore) ds.Datastore { + return &ds10{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + } + }, + 11: func(dstore ds.Datastore) ds.Datastore { + return &ds11{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + } + }, + 12: func(dstore ds.Datastore) ds.Datastore { + return &ds12{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + } + }, + 13: func(dstore ds.Datastore) ds.Datastore { + return &ds13{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + } + }, + 14: func(dstore ds.Datastore) ds.Datastore { + return &ds14{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + } + }, + 15: func(dstore ds.Datastore) ds.Datastore { + return &ds15{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + } + }, + 16: func(dstore ds.Datastore) ds.Datastore { + return &ds16{ + Datastore: dstore, + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 17: func(dstore ds.Datastore) ds.Datastore { + return &ds17{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 18: func(dstore ds.Datastore) ds.Datastore { + return &ds18{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 19: func(dstore ds.Datastore) ds.Datastore { + return &ds19{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 20: func(dstore ds.Datastore) ds.Datastore { + return &ds20{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 21: func(dstore ds.Datastore) ds.Datastore { + return &ds21{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 22: func(dstore ds.Datastore) ds.Datastore { + return &ds22{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 23: func(dstore ds.Datastore) ds.Datastore { + return &ds23{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 24: func(dstore ds.Datastore) ds.Datastore { + return &ds24{ + Datastore: dstore, + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 25: func(dstore ds.Datastore) ds.Datastore { + return &ds25{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 26: func(dstore ds.Datastore) ds.Datastore { + return &ds26{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 27: func(dstore ds.Datastore) ds.Datastore { + return &ds27{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 28: func(dstore ds.Datastore) ds.Datastore { + return &ds28{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 29: func(dstore ds.Datastore) ds.Datastore { + return &ds29{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 30: func(dstore ds.Datastore) ds.Datastore { + return &ds30{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 31: func(dstore ds.Datastore) ds.Datastore { + return &ds31{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + } + }, + 32: func(dstore ds.Datastore) ds.Datastore { + return &ds32{ + Datastore: dstore, + TTL: dstore.(ds.TTLDatastore), + } + }, + 33: func(dstore ds.Datastore) ds.Datastore { + return &ds33{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + TTL: dstore.(ds.TTLDatastore), + } + }, + 34: func(dstore ds.Datastore) ds.Datastore { + return &ds34{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 35: func(dstore ds.Datastore) ds.Datastore { + return &ds35{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 36: func(dstore ds.Datastore) ds.Datastore { + return &ds36{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 37: func(dstore ds.Datastore) ds.Datastore { + return &ds37{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 38: func(dstore ds.Datastore) ds.Datastore { + return &ds38{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 39: func(dstore ds.Datastore) ds.Datastore { + return &ds39{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 40: func(dstore ds.Datastore) ds.Datastore { + return &ds40{ + Datastore: dstore, + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 41: func(dstore ds.Datastore) ds.Datastore { + return &ds41{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 42: func(dstore ds.Datastore) ds.Datastore { + return &ds42{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 43: func(dstore ds.Datastore) ds.Datastore { + return &ds43{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 44: func(dstore ds.Datastore) ds.Datastore { + return &ds44{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 45: func(dstore ds.Datastore) ds.Datastore { + return &ds45{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 46: func(dstore ds.Datastore) ds.Datastore { + return &ds46{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 47: func(dstore ds.Datastore) ds.Datastore { + return &ds47{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 48: func(dstore ds.Datastore) ds.Datastore { + return &ds48{ + Datastore: dstore, + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 49: func(dstore ds.Datastore) ds.Datastore { + return &ds49{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 50: func(dstore ds.Datastore) ds.Datastore { + return &ds50{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 51: func(dstore ds.Datastore) ds.Datastore { + return &ds51{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 52: func(dstore ds.Datastore) ds.Datastore { + return &ds52{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 53: func(dstore ds.Datastore) ds.Datastore { + return &ds53{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 54: func(dstore ds.Datastore) ds.Datastore { + return &ds54{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 55: func(dstore ds.Datastore) ds.Datastore { + return &ds55{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 56: func(dstore ds.Datastore) ds.Datastore { + return &ds56{ + Datastore: dstore, + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 57: func(dstore ds.Datastore) ds.Datastore { + return &ds57{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 58: func(dstore ds.Datastore) ds.Datastore { + return &ds58{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 59: func(dstore ds.Datastore) ds.Datastore { + return &ds59{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 60: func(dstore ds.Datastore) ds.Datastore { + return &ds60{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 61: func(dstore ds.Datastore) ds.Datastore { + return &ds61{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 62: func(dstore ds.Datastore) ds.Datastore { + return &ds62{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 63: func(dstore ds.Datastore) ds.Datastore { + return &ds63{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + } + }, + 64: func(dstore ds.Datastore) ds.Datastore { + return &ds64{ + Datastore: dstore, + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 65: func(dstore ds.Datastore) ds.Datastore { + return &ds65{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 66: func(dstore ds.Datastore) ds.Datastore { + return &ds66{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 67: func(dstore ds.Datastore) ds.Datastore { + return &ds67{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 68: func(dstore ds.Datastore) ds.Datastore { + return &ds68{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 69: func(dstore ds.Datastore) ds.Datastore { + return &ds69{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 70: func(dstore ds.Datastore) ds.Datastore { + return &ds70{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 71: func(dstore ds.Datastore) ds.Datastore { + return &ds71{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 72: func(dstore ds.Datastore) ds.Datastore { + return &ds72{ + Datastore: dstore, + PersistentFeature: dstore.(ds.PersistentDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 73: func(dstore ds.Datastore) ds.Datastore { + return &ds73{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + PersistentFeature: dstore.(ds.PersistentDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 74: func(dstore ds.Datastore) ds.Datastore { + return &ds74{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 75: func(dstore ds.Datastore) ds.Datastore { + return &ds75{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 76: func(dstore ds.Datastore) ds.Datastore { + return &ds76{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 77: func(dstore ds.Datastore) ds.Datastore { + return &ds77{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 78: func(dstore ds.Datastore) ds.Datastore { + return &ds78{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 79: func(dstore ds.Datastore) ds.Datastore { + return &ds79{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 80: func(dstore ds.Datastore) ds.Datastore { + return &ds80{ + Datastore: dstore, + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 81: func(dstore ds.Datastore) ds.Datastore { + return &ds81{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 82: func(dstore ds.Datastore) ds.Datastore { + return &ds82{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 83: func(dstore ds.Datastore) ds.Datastore { + return &ds83{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 84: func(dstore ds.Datastore) ds.Datastore { + return &ds84{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 85: func(dstore ds.Datastore) ds.Datastore { + return &ds85{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 86: func(dstore ds.Datastore) ds.Datastore { + return &ds86{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 87: func(dstore ds.Datastore) ds.Datastore { + return &ds87{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 88: func(dstore ds.Datastore) ds.Datastore { + return &ds88{ + Datastore: dstore, + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 89: func(dstore ds.Datastore) ds.Datastore { + return &ds89{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 90: func(dstore ds.Datastore) ds.Datastore { + return &ds90{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 91: func(dstore ds.Datastore) ds.Datastore { + return &ds91{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 92: func(dstore ds.Datastore) ds.Datastore { + return &ds92{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 93: func(dstore ds.Datastore) ds.Datastore { + return &ds93{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 94: func(dstore ds.Datastore) ds.Datastore { + return &ds94{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 95: func(dstore ds.Datastore) ds.Datastore { + return &ds95{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 96: func(dstore ds.Datastore) ds.Datastore { + return &ds96{ + Datastore: dstore, + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 97: func(dstore ds.Datastore) ds.Datastore { + return &ds97{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 98: func(dstore ds.Datastore) ds.Datastore { + return &ds98{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 99: func(dstore ds.Datastore) ds.Datastore { + return &ds99{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 100: func(dstore ds.Datastore) ds.Datastore { + return &ds100{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 101: func(dstore ds.Datastore) ds.Datastore { + return &ds101{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 102: func(dstore ds.Datastore) ds.Datastore { + return &ds102{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 103: func(dstore ds.Datastore) ds.Datastore { + return &ds103{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 104: func(dstore ds.Datastore) ds.Datastore { + return &ds104{ + Datastore: dstore, + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 105: func(dstore ds.Datastore) ds.Datastore { + return &ds105{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 106: func(dstore ds.Datastore) ds.Datastore { + return &ds106{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 107: func(dstore ds.Datastore) ds.Datastore { + return &ds107{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 108: func(dstore ds.Datastore) ds.Datastore { + return &ds108{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 109: func(dstore ds.Datastore) ds.Datastore { + return &ds109{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 110: func(dstore ds.Datastore) ds.Datastore { + return &ds110{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 111: func(dstore ds.Datastore) ds.Datastore { + return &ds111{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 112: func(dstore ds.Datastore) ds.Datastore { + return &ds112{ + Datastore: dstore, + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 113: func(dstore ds.Datastore) ds.Datastore { + return &ds113{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 114: func(dstore ds.Datastore) ds.Datastore { + return &ds114{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 115: func(dstore ds.Datastore) ds.Datastore { + return &ds115{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 116: func(dstore ds.Datastore) ds.Datastore { + return &ds116{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 117: func(dstore ds.Datastore) ds.Datastore { + return &ds117{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 118: func(dstore ds.Datastore) ds.Datastore { + return &ds118{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 119: func(dstore ds.Datastore) ds.Datastore { + return &ds119{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 120: func(dstore ds.Datastore) ds.Datastore { + return &ds120{ + Datastore: dstore, + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 121: func(dstore ds.Datastore) ds.Datastore { + return &ds121{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 122: func(dstore ds.Datastore) ds.Datastore { + return &ds122{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 123: func(dstore ds.Datastore) ds.Datastore { + return &ds123{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 124: func(dstore ds.Datastore) ds.Datastore { + return &ds124{ + Datastore: dstore, + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 125: func(dstore ds.Datastore) ds.Datastore { + return &ds125{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 126: func(dstore ds.Datastore) ds.Datastore { + return &ds126{ + Datastore: dstore, + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, + 127: func(dstore ds.Datastore) ds.Datastore { + return &ds127{ + Datastore: dstore, + BatchingFeature: dstore.(ds.Batching), + CheckedFeature: dstore.(ds.CheckedDatastore), + GCFeature: dstore.(ds.GCDatastore), + PersistentFeature: dstore.(ds.PersistentDatastore), + ScrubbedFeature: dstore.(ds.ScrubbedDatastore), + TTL: dstore.(ds.TTLDatastore), + TxnFeature: dstore.(ds.TxnDatastore), + } + }, +} diff --git a/scoped/scoped.go b/scoped/scoped.go new file mode 100644 index 0000000..7b663df --- /dev/null +++ b/scoped/scoped.go @@ -0,0 +1,42 @@ +package scoped + +import ( + ds "github.com/ipfs/go-datastore" +) + +func getFeatureSet(dstore ds.Datastore) map[interface{}]bool { + features := ds.FeaturesForDatastore(dstore) + featureSet := map[interface{}]bool{} + for _, f := range features { + featureSet[f.Interface] = true + } + return featureSet +} + +// Wrap returns a datastore based on the source, whose concrete type is scoped down to only the features supported by the target. +func Wrap(source ds.Datastore, target ds.Datastore) ds.Datastore { + if source == nil || target == nil { + return nil + } + return WithFeatures(source, ds.FeaturesForDatastore(target)) +} + +// WithFeatures returns a wrapped datastore that implements the intersection of the given datastore's features with the provided features. +func WithFeatures(dstore ds.Datastore, features []ds.Feature) ds.Datastore { + dstoreFeatures := getFeatureSet(dstore) + + dstoreFeatureSet := map[string]bool{} + for _, f := range features { + if _, ok := dstoreFeatures[f.Interface]; ok { + dstoreFeatureSet[f.Name] = true + } + } + + ctor := 0 + for i, f := range features { + if _, ok := dstoreFeatureSet[f.Name]; ok { + ctor += (1 << i) + } + } + return ctors[ctor](dstore) +} diff --git a/scoped/scoped_test.go b/scoped/scoped_test.go new file mode 100644 index 0000000..4f5d035 --- /dev/null +++ b/scoped/scoped_test.go @@ -0,0 +1,55 @@ +package scoped + +import ( + "reflect" + "testing" + + ds "github.com/ipfs/go-datastore" +) + +func TestWithFeatures(t *testing.T) { + cases := []struct { + name string + dstore ds.Datastore + features []ds.Feature + + expectedFeatures []ds.Feature + }{ + { + name: "no features should return a base datastore", + dstore: &ds.MapDatastore{}, + features: nil, + expectedFeatures: nil, + }, + { + name: "identity case", + dstore: &ds.MapDatastore{}, + features: ds.FeaturesByNames("Batching"), + expectedFeatures: ds.FeaturesByNames("Batching"), + }, + { + name: "should scope down correctly", + dstore: &ds.LogDatastore{}, + features: ds.FeaturesByNames("Batching"), + expectedFeatures: ds.FeaturesByNames("Batching"), + }, + { + name: "takes intersection of features", + dstore: &ds.MapDatastore{}, + features: ds.FeaturesByNames("Batching", "Checked"), + expectedFeatures: ds.FeaturesByNames("Batching"), + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + new := WithFeatures(c.dstore, c.features) + newFeats := ds.FeaturesForDatastore(new) + if len(newFeats) != len(c.expectedFeatures) { + t.Fatalf("expected %d features, got %v", len(c.expectedFeatures), newFeats) + } + if !reflect.DeepEqual(newFeats, c.expectedFeatures) { + t.Fatalf("expected features %v, got %v", c.expectedFeatures, newFeats) + } + }) + } +}