diff --git a/dgraph/cmd/live/batch.go b/dgraph/cmd/live/batch.go index 5c6c0461609..70d9fcb33b1 100644 --- a/dgraph/cmd/live/batch.go +++ b/dgraph/cmd/live/batch.go @@ -87,7 +87,7 @@ type loader struct { reqNum uint64 reqs chan *request zeroconn *grpc.ClientConn - schema *schema + schema *Schema namespaces map[uint64]struct{} upsertLock sync.RWMutex @@ -240,7 +240,7 @@ func createValueEdge(nq *api.NQuad, sid uint64) (*pb.DirectedEdge, error) { return p, nil } -func fingerprintEdge(t *pb.DirectedEdge, pred *predicate) uint64 { +func fingerprintEdge(t *pb.DirectedEdge, pred *Predicate) uint64 { var id uint64 = math.MaxUint64 // Value with a lang type. diff --git a/dgraph/cmd/live/run.go b/dgraph/cmd/live/run.go index d20c0bf4a7e..e33db2acea1 100644 --- a/dgraph/cmd/live/run.go +++ b/dgraph/cmd/live/run.go @@ -78,7 +78,7 @@ type options struct { preserveNs bool } -type predicate struct { +type Predicate struct { Predicate string `json:"predicate,omitempty"` Type string `json:"type,omitempty"` Tokenizer []string `json:"tokenizer,omitempty"` @@ -89,12 +89,13 @@ type predicate struct { Upsert bool `json:"upsert,omitempty"` Reverse bool `json:"reverse,omitempty"` NoConflict bool `json:"no_conflict,omitempty"` + Unique bool `json:"unique,omitempty"` ValueType types.TypeID } -type schema struct { - Predicates []*predicate `json:"schema,omitempty"` - preds map[string]*predicate +type Schema struct { + Predicates []*Predicate `json:"schema,omitempty"` + preds map[string]*Predicate } type request struct { @@ -102,8 +103,8 @@ type request struct { conflicts []uint64 } -func (l *schema) init(ns uint64, galaxyOperation bool) { - l.preds = make(map[string]*predicate) +func (l *Schema) init(ns uint64, galaxyOperation bool) { + l.preds = make(map[string]*Predicate) for _, i := range l.Predicates { i.ValueType, _ = types.TypeForName(i.Type) if !galaxyOperation { @@ -115,7 +116,7 @@ func (l *schema) init(ns uint64, galaxyOperation bool) { var ( opt options - sch schema + sch Schema // Live is the sub-command invoked when running "dgraph live". Live x.SubCommand @@ -185,7 +186,7 @@ func init() { "specific namespace. Setting it to negative value will preserve the namespace.") } -func getSchema(ctx context.Context, dgraphClient *dgo.Dgraph, galaxyOperation bool) (*schema, error) { +func getSchema(ctx context.Context, dgraphClient *dgo.Dgraph, galaxyOperation bool) (*Schema, error) { txn := dgraphClient.NewTxn() defer func() { if err := txn.Discard(ctx); err != nil { @@ -500,7 +501,7 @@ func (l *loader) processLoadFile(ctx context.Context, rd *bufio.Reader, ck chunk sort.Slice(buffer, func(i, j int) bool { iPred := sch.preds[x.NamespaceAttr(buffer[i].Namespace, buffer[i].Predicate)] jPred := sch.preds[x.NamespaceAttr(buffer[j].Namespace, buffer[j].Predicate)] - t := func(a *predicate) int { + t := func(a *Predicate) int { if a != nil && a.Count { return 1 } @@ -683,7 +684,7 @@ func (l *loader) populateNamespaces(ctx context.Context, dc *dgo.Dgraph, singleN return err } - var sch schema + var sch Schema err = json.Unmarshal(res.GetJson(), &sch) if err != nil { return err diff --git a/dgraphtest/cluster.go b/dgraphtest/cluster.go index ee3358f9776..b8e63a397c4 100644 --- a/dgraphtest/cluster.go +++ b/dgraphtest/cluster.go @@ -646,6 +646,20 @@ func (gc *GrpcClient) Mutate(mu *api.Mutation) (*api.Response, error) { return txn.Mutate(ctx, mu) } +func (gc *GrpcClient) Upsert(query string, mu *api.Mutation) (*api.Response, error) { + txn := gc.NewTxn() + defer func() { _ = txn.Discard(context.Background()) }() + + ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) + defer cancel() + req := &api.Request{ + Query: query, + Mutations: []*api.Mutation{mu}, + CommitNow: true, + } + return txn.Do(ctx, req) +} + // Query performa a given query in a new txn func (gc *GrpcClient) Query(query string) (*api.Response, error) { txn := gc.NewTxn() diff --git a/edgraph/server.go b/edgraph/server.go index 642b50f1762..85f1323ff72 100644 --- a/edgraph/server.go +++ b/edgraph/server.go @@ -68,6 +68,12 @@ const ( type GraphqlContextKey int +// uniquePredMeta stores the query variable name from 'uniqueQuery' +type uniquePredMeta struct { + queryVar string + valVar string +} + const ( // IsGraphql is used to validate requests which are allowed to mutate GraphQL reserved // predicates, like dgraph.graphql.schema and dgraph.graphql.xid. @@ -570,6 +576,10 @@ func (s *Server) doMutate(ctx context.Context, qc *queryContext, resp *api.Respo return err } + if err := verifyUniqueWithinMutation(qc); err != nil { + return err + } + newUids, err := query.AssignUids(ctx, qc.gmuList) if err != nil { return err @@ -738,7 +748,7 @@ func buildUpsertQuery(qc *queryContext) string { for i, gmu := range qc.gmuList { isCondUpsert := strings.TrimSpace(gmu.Cond) != "" if isCondUpsert { - qc.condVars[i] = "__dgraph__" + strconv.Itoa(i) + qc.condVars[i] = fmt.Sprintf("__dgraph_upsertcheck_%v__", strconv.Itoa(i)) qc.uidRes[qc.condVars[i]] = nil // @if in upsert is same as @filter in the query cond := strings.Replace(gmu.Cond, "@if", "@filter", 1) @@ -828,6 +838,17 @@ func findMutationVars(qc *queryContext) []string { varsList = append(varsList, v) } + // We use certain variables to check uniqueness. To prevent errors related to unused + // variables, we explicitly add them to the 'varsList' since they are not used in the mutation. + for _, uniqueQueryVar := range qc.uniqueVars { + varsList = append(varsList, uniqueQueryVar.queryVar) + // If the triple contains a "val()" in objectId, we need to add + // one more variable to the unique query. So, we explicitly add it to the varList. + if uniqueQueryVar.valVar != "" { + varsList = append(varsList, uniqueQueryVar.valVar) + } + } + return varsList } @@ -1046,6 +1067,9 @@ type queryContext struct { // 1B) and resulting in OOM. We are limiting number of nquads which can be inserted in // a single request. nquadsCount int + // uniqueVar stores the mapping between the indexes of gmuList and gmu.Set, + // along with their respective uniqueQueryVariables. + uniqueVars map[uint64]uniquePredMeta } // Request represents a query request sent to the doQuery() method on the Server. @@ -1517,6 +1541,10 @@ func processQuery(ctx context.Context, qc *queryContext) (*api.Response, error) qc.valRes[name] = v.Vals } + if err := verifyUnique(qc, qr); err != nil { + return resp, err + } + resp.Metrics = &api.Metrics{ NumUids: er.Metrics, } @@ -1550,6 +1578,10 @@ func parseRequest(qc *queryContext) error { qc.gmuList = append(qc.gmuList, gmu) } + if err := addQueryIfUnique(qc); err != nil { + return err + } + qc.uidRes = make(map[string][]string) qc.valRes = make(map[string]map[uint64]types.Val) upsertQuery = buildUpsertQuery(qc) @@ -1575,6 +1607,168 @@ func parseRequest(qc *queryContext) error { return validateQuery(qc.dqlRes.Query) } +// verifyUnique verifies uniqueness of mutation +func verifyUnique(qc *queryContext, qr query.Request) error { + if len(qc.uniqueVars) == 0 { + return nil + } + + for i, queryVar := range qc.uniqueVars { + gmuIndex, rdfIndex := decodeIndex(i) + pred := qc.gmuList[gmuIndex].Set[rdfIndex] + queryResult := qr.Vars[queryVar.queryVar] + if !isUpsertCondTrue(qc, int(gmuIndex)) { + continue + } + isEmpty := func(l *pb.List) bool { + return l == nil || len(l.Uids) == 0 + } + + var subjectUid uint64 + if strings.HasPrefix(pred.Subject, "uid(") { + varName := qr.Vars[pred.Subject[4:len(pred.Subject)-1]] + if isEmpty(varName.Uids) { + subjectUid = 0 // blank node + } else if len(varName.Uids.Uids) == 1 { + subjectUid = varName.Uids.Uids[0] + } else { + return errors.Errorf("unique constraint violated for predicate [%v]", pred.Predicate) + } + } else { + var err error + subjectUid, err = parseSubject(pred.Subject) + if err != nil { + return errors.Wrapf(err, "error while parsing [%v]", pred.Subject) + } + } + + var predValue interface{} + if strings.HasPrefix(pred.ObjectId, "val(") { + varName := qr.Vars[pred.ObjectId[4:len(pred.ObjectId)-1]] + val, ok := varName.Vals[0] + if !ok { + _, isValueGoingtoSet := varName.Vals[subjectUid] + if !isValueGoingtoSet { + continue + } + + results := qr.Vars[queryVar.valVar] + for uidOfv, v := range results.Vals { + if v.Value == varName.Vals[subjectUid].Value && uidOfv != subjectUid { + return errors.Errorf("could not insert duplicate value [%v] for predicate [%v]", + v.Value, pred.Predicate) + } + } + continue + } else { + predValue = val.Value + } + } else { + predValue = dql.TypeValFrom(pred.ObjectValue).Value + } + + // Here, we check the uniqueness of the triple by comparing the result of the uniqueQuery with the triple. + if !isEmpty(queryResult.Uids) { + if len(queryResult.Uids.Uids) > 1 { + glog.Errorf("unique constraint violated for predicate [%v].uids: [%v].namespace: [%v]", + pred.Predicate, queryResult.Uids.Uids, pred.Namespace) + return errors.Errorf("there are duplicates in existing data for predicate [%v]."+ + "Please drop the unique constraint and re-add it after fixing the predicate data", pred.Predicate) + } else if queryResult.Uids.Uids[0] != subjectUid { + // Determine whether the mutation is a swap mutation + isSwap, err := isSwap(qc, queryResult.Uids.Uids[0], pred.Predicate) + if err != nil { + return err + } + if !isSwap { + return errors.Errorf("could not insert duplicate value [%v] for predicate [%v]", + predValue, pred.Predicate) + } + } + } + } + return nil +} + +// addQueryIfUnique adds dummy queries in the request for checking whether predicate is unique in the db +func addQueryIfUnique(qc *queryContext) error { + if len(qc.gmuList) == 0 { + return nil + } + + ctx := context.WithValue(context.Background(), schema.IsWrite, false) + qc.uniqueVars = map[uint64]uniquePredMeta{} + var buildQuery strings.Builder + for gmuIndex, gmu := range qc.gmuList { + for rdfIndex, pred := range gmu.Set { + predSchema, _ := schema.State().Get(ctx, x.NamespaceAttr(pred.Namespace, pred.Predicate)) + if !predSchema.Unique { + continue + } + var predicateName string + if pred.Lang != "" { + predicateName = fmt.Sprintf(pred.Predicate+"@%v", pred.Lang) + } else { + predicateName = pred.Predicate + } + uniqueVarMapKey := encodeIndex(gmuIndex, rdfIndex) + queryVar := fmt.Sprintf("__dgraph_uniquecheck_%v__", uniqueVarMapKey) + // Now, we add a query for a predicate to check if the value of the + // predicate sent in the mutation already exists in the DB. + // For example, schema => email: string @unique @index(exact) .\ + // + // To ensure uniqueness of values of email predicate, we will query for the value + // to ensure that we are not adding a duplicate value. + // + // There are following use-cases of mutations which we need to handle: + // 1. _:a "example@email.com" . + // 2. _:a val(queryVariable) . + // In the code below, we construct respective query for the above use-cases viz. + // __dgraph_uniquecheck_1__ as var(func: eq(email,"example@email.com")) + // __dgraph_uniquecheck_2__ as var(func: eq(email, val(queryVariable))){ + // uid + // __dgraph_uniquecheck_val_2__ as email + // } + // Each of the above query will check if there is already an existing value. + // We can be sure that we may get at most one UID in return. + // If the returned UID is different than the UID we have + // in the mutation, then we reject the mutation. + + if !strings.HasPrefix(pred.ObjectId, "val(") { + query := fmt.Sprintf(`%v as var(func: eq(%v,"%v"))`, queryVar, predicateName, + dql.TypeValFrom(pred.ObjectValue).Value) + if _, err := buildQuery.WriteString(query); err != nil { + return errors.Wrapf(err, "error while writing string") + } + qc.uniqueVars[uniqueVarMapKey] = uniquePredMeta{queryVar: queryVar} + } else { + valQueryVar := fmt.Sprintf("__dgraph_uniquecheck_val_%v__", uniqueVarMapKey) + query := fmt.Sprintf(`%v as var(func: eq(%v,%v)){ + uid + %v as %v + }`, queryVar, predicateName, pred.ObjectId, valQueryVar, predicateName) + if _, err := buildQuery.WriteString(query); err != nil { + return errors.Wrapf(err, "error while building unique query") + } + qc.uniqueVars[uniqueVarMapKey] = uniquePredMeta{valVar: valQueryVar, queryVar: queryVar} + } + } + + if buildQuery.Len() > 0 { + if _, err := buildQuery.WriteString("}"); err != nil { + return errors.Wrapf(err, "error while writing string") + } + if qc.req.Query == "" { + qc.req.Query = "{" + buildQuery.String() + } else { + qc.req.Query = strings.TrimRight(qc.req.Query, "}") + qc.req.Query = qc.req.Query + buildQuery.String() + } + } + } + return nil +} + func authorizeRequest(ctx context.Context, qc *queryContext) error { if err := authorizeQuery(ctx, &qc.dqlRes, qc.graphql); err != nil { return err @@ -1912,3 +2106,87 @@ func isDropAll(op *api.Operation) bool { } return false } + +func verifyUniqueWithinMutation(qc *queryContext) error { + if len(qc.uniqueVars) == 0 { + return nil + } + + for i := range qc.uniqueVars { + gmuIndex, rdfIndex := decodeIndex(i) + if len(qc.gmuList[gmuIndex].Set) == 0 { + return nil + } + pred1 := qc.gmuList[gmuIndex].Set[rdfIndex] + pred1Value := dql.TypeValFrom(pred1.ObjectValue).Value + for j := range qc.uniqueVars { + gmuIndex2, rdfIndex2 := decodeIndex(j) + pred2 := qc.gmuList[gmuIndex2].Set[rdfIndex2] + if pred2.Predicate == pred1.Predicate && dql.TypeValFrom(pred2.ObjectValue).Value == pred1Value && + pred2.Subject != pred1.Subject { + return errors.Errorf("could not insert duplicate value [%v] for predicate [%v]", + dql.TypeValFrom(pred1.ObjectValue).Value, pred1.Predicate) + } + } + } + return nil +} + +func isUpsertCondTrue(qc *queryContext, gmuIndex int) bool { + condVar := qc.condVars[gmuIndex] + if condVar == "" { + return true + } + + uids, ok := qc.uidRes[condVar] + return ok && len(uids) == 1 +} + +func isSwap(qc *queryContext, pred1SubjectUid uint64, pred1Predicate string) (bool, error) { + for i := range qc.uniqueVars { + gmuIndex, rdfIndex := decodeIndex(i) + pred2 := qc.gmuList[gmuIndex].Set[rdfIndex] + var pred2SubjectUid uint64 + if !strings.HasPrefix(pred2.Subject, "uid(") { + var err error + pred2SubjectUid, err = parseSubject(pred2.Subject) + if err != nil { + return false, errors.Wrapf(err, "error while parsing [%v]", pred2.Subject) + } + } else { + pred2SubjectUid = 0 + } + + if pred2SubjectUid == pred1SubjectUid && pred1Predicate == pred2.Predicate { + return true, nil + } + } + return false, nil +} + +// encodeBit two uint32 numbers by bit. +// First 32 bits store k1 and last 32 bits store k2. +func encodeIndex(k1, k2 int) uint64 { + safeToConvert := func(num int) { + if num > math.MaxUint32 { + panic("unsafe conversion: integer value is too large for uint32") + } + } + safeToConvert(k1) + safeToConvert(k2) + return uint64(uint32(k1))<<32 | uint64(uint32(k2)) +} + +func decodeIndex(pair uint64) (uint32, uint32) { + k1 := uint32(pair >> 32) + k2 := uint32(pair) & 0xFFFFFFFF + return k1, k2 +} + +func parseSubject(predSubject string) (uint64, error) { + if strings.HasPrefix(predSubject, "_:") { + return 0, nil // blank node + } else { + return dql.ParseUid(predSubject) + } +} diff --git a/go.mod b/go.mod index 634c273b634..1595c2b587b 100644 --- a/go.mod +++ b/go.mod @@ -61,6 +61,7 @@ require ( golang.org/x/text v0.12.0 golang.org/x/tools v0.9.3 google.golang.org/grpc v1.56.2 + google.golang.org/protobuf v1.31.0 gopkg.in/square/go-jose.v2 v2.3.1 gopkg.in/yaml.v2 v2.4.0 ) @@ -142,7 +143,6 @@ require ( google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect google.golang.org/grpc/examples v0.0.0-20230821201920-d51b3f41716d // indirect - google.golang.org/protobuf v1.31.0 // indirect gopkg.in/DataDog/dd-trace-go.v1 v1.22.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/protos/pb.proto b/protos/pb.proto index 252c73c3814..7cc0e2fc239 100644 --- a/protos/pb.proto +++ b/protos/pb.proto @@ -475,6 +475,7 @@ message SchemaNode { bool upsert = 8; bool lang = 9; bool no_conflict = 10; + bool unique = 11; } message SchemaResult { @@ -496,6 +497,7 @@ message SchemaUpdate { bool list = 6; bool upsert = 8; bool lang = 9; + bool unique = 14; // Fields required for type system. bool non_nullable = 10; diff --git a/protos/pb/pb.pb.go b/protos/pb/pb.pb.go index eb4bd1ca981..6c8aef3d819 100644 --- a/protos/pb/pb.pb.go +++ b/protos/pb/pb.pb.go @@ -3397,6 +3397,7 @@ type SchemaNode struct { Upsert bool `protobuf:"varint,8,opt,name=upsert,proto3" json:"upsert,omitempty"` Lang bool `protobuf:"varint,9,opt,name=lang,proto3" json:"lang,omitempty"` NoConflict bool `protobuf:"varint,10,opt,name=no_conflict,json=noConflict,proto3" json:"no_conflict,omitempty"` + Unique bool `protobuf:"varint,11,opt,name=unique,proto3" json:"unique,omitempty"` } func (m *SchemaNode) Reset() { *m = SchemaNode{} } @@ -3502,6 +3503,13 @@ func (m *SchemaNode) GetNoConflict() bool { return false } +func (m *SchemaNode) GetUnique() bool { + if m != nil { + return m.Unique + } + return false +} + type SchemaResult struct { Schema []*SchemaNode `protobuf:"bytes,1,rep,name=schema,proto3" json:"schema,omitempty"` // Deprecated: Do not use. } @@ -3556,6 +3564,7 @@ type SchemaUpdate struct { List bool `protobuf:"varint,6,opt,name=list,proto3" json:"list,omitempty"` Upsert bool `protobuf:"varint,8,opt,name=upsert,proto3" json:"upsert,omitempty"` Lang bool `protobuf:"varint,9,opt,name=lang,proto3" json:"lang,omitempty"` + Unique bool `protobuf:"varint,14,opt,name=unique,proto3" json:"unique,omitempty"` // Fields required for type system. NonNullable bool `protobuf:"varint,10,opt,name=non_nullable,json=nonNullable,proto3" json:"non_nullable,omitempty"` NonNullableList bool `protobuf:"varint,11,opt,name=non_nullable_list,json=nonNullableList,proto3" json:"non_nullable_list,omitempty"` @@ -3654,6 +3663,13 @@ func (m *SchemaUpdate) GetLang() bool { return false } +func (m *SchemaUpdate) GetUnique() bool { + if m != nil { + return m.Unique + } + return false +} + func (m *SchemaUpdate) GetNonNullable() bool { if m != nil { return m.NonNullable @@ -5659,351 +5675,352 @@ func init() { func init() { proto.RegisterFile("pb.proto", fileDescriptor_f80abaa17e25ccc8) } var fileDescriptor_f80abaa17e25ccc8 = []byte{ - // 5495 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x7b, 0x4b, 0x6f, 0x1c, 0x57, - 0x76, 0x30, 0xab, 0x9f, 0x55, 0xa7, 0x1f, 0x6c, 0x5e, 0xc9, 0x72, 0x4f, 0xcb, 0x12, 0xe9, 0xb2, - 0x65, 0xd3, 0x92, 0x45, 0x49, 0xb4, 0x67, 0xbe, 0xb1, 0x07, 0x03, 0x7c, 0x7c, 0x34, 0x65, 0x5a, - 0x14, 0xc9, 0xa9, 0x6e, 0x6a, 0x1e, 0x40, 0xd2, 0x28, 0x56, 0x5d, 0x92, 0x35, 0xac, 0xae, 0xaa, - 0xa9, 0xaa, 0xe6, 0x90, 0xde, 0x05, 0x01, 0x32, 0x9b, 0x2c, 0x06, 0xc8, 0x26, 0xab, 0x00, 0xc9, - 0x36, 0x59, 0x05, 0x01, 0x12, 0x04, 0xc8, 0x2e, 0x08, 0x06, 0x59, 0xcd, 0x32, 0xc8, 0x24, 0x42, - 0x60, 0x07, 0x59, 0x68, 0x11, 0x20, 0xc8, 0x0f, 0x48, 0x70, 0xce, 0xbd, 0xf5, 0x6a, 0x36, 0x65, - 0xc9, 0x41, 0x36, 0x59, 0xf5, 0x3d, 0xe7, 0xbe, 0xcf, 0x3d, 0xef, 0x53, 0x0d, 0x6a, 0x70, 0xb8, - 0x12, 0x84, 0x7e, 0xec, 0xb3, 0x52, 0x70, 0xd8, 0xd3, 0xcc, 0xc0, 0x11, 0x60, 0xef, 0xee, 0xb1, - 0x13, 0x9f, 0x4c, 0x0e, 0x57, 0x2c, 0x7f, 0xfc, 0xc0, 0x3e, 0x0e, 0xcd, 0xe0, 0xe4, 0xbe, 0xe3, - 0x3f, 0x38, 0x34, 0xed, 0x63, 0x1e, 0x3e, 0x38, 0xfb, 0xf8, 0x41, 0x70, 0xf8, 0x20, 0x99, 0xda, - 0xbb, 0x9f, 0x1b, 0x7b, 0xec, 0x1f, 0xfb, 0x0f, 0x08, 0x7d, 0x38, 0x39, 0x22, 0x88, 0x00, 0x6a, - 0x89, 0xe1, 0x7a, 0x0f, 0x2a, 0x3b, 0x4e, 0x14, 0x33, 0x06, 0x95, 0x89, 0x63, 0x47, 0x5d, 0x65, - 0xa9, 0xbc, 0x5c, 0x33, 0xa8, 0xad, 0x3f, 0x05, 0x6d, 0x68, 0x46, 0xa7, 0xcf, 0x4c, 0x77, 0xc2, - 0x59, 0x07, 0xca, 0x67, 0xa6, 0xdb, 0x55, 0x96, 0x94, 0xe5, 0xa6, 0x81, 0x4d, 0xb6, 0x02, 0xea, - 0x99, 0xe9, 0x8e, 0xe2, 0x8b, 0x80, 0x77, 0x4b, 0x4b, 0xca, 0x72, 0x7b, 0xf5, 0xda, 0x4a, 0x70, - 0xb8, 0xb2, 0xef, 0x47, 0xb1, 0xe3, 0x1d, 0xaf, 0x3c, 0x33, 0xdd, 0xe1, 0x45, 0xc0, 0x8d, 0xfa, - 0x99, 0x68, 0xe8, 0x7b, 0xd0, 0x18, 0x84, 0xd6, 0xd6, 0xc4, 0xb3, 0x62, 0xc7, 0xf7, 0x70, 0x47, - 0xcf, 0x1c, 0x73, 0x5a, 0x51, 0x33, 0xa8, 0x8d, 0x38, 0x33, 0x3c, 0x8e, 0xba, 0xe5, 0xa5, 0x32, - 0xe2, 0xb0, 0xcd, 0xba, 0x50, 0x77, 0xa2, 0x0d, 0x7f, 0xe2, 0xc5, 0xdd, 0xca, 0x92, 0xb2, 0xac, - 0x1a, 0x09, 0xa8, 0xff, 0x65, 0x19, 0xaa, 0x3f, 0x98, 0xf0, 0xf0, 0x82, 0xe6, 0xc5, 0x71, 0x98, - 0xac, 0x85, 0x6d, 0x76, 0x1d, 0xaa, 0xae, 0xe9, 0x1d, 0x47, 0xdd, 0x12, 0x2d, 0x26, 0x00, 0x76, - 0x13, 0x34, 0xf3, 0x28, 0xe6, 0xe1, 0x68, 0xe2, 0xd8, 0xdd, 0xf2, 0x92, 0xb2, 0x5c, 0x33, 0x54, - 0x42, 0x1c, 0x38, 0x36, 0xfb, 0x16, 0xa8, 0xb6, 0x3f, 0xb2, 0xf2, 0x7b, 0xd9, 0x3e, 0xed, 0xc5, - 0xde, 0x01, 0x75, 0xe2, 0xd8, 0x23, 0xd7, 0x89, 0xe2, 0x6e, 0x75, 0x49, 0x59, 0x6e, 0xac, 0xaa, - 0x78, 0x59, 0xa4, 0x9d, 0x51, 0x9f, 0x38, 0x36, 0x11, 0xf1, 0x2e, 0xa8, 0x51, 0x68, 0x8d, 0x8e, - 0x26, 0x9e, 0xd5, 0xad, 0xd1, 0xa0, 0x79, 0x1c, 0x94, 0xbb, 0xb5, 0x51, 0x8f, 0x04, 0x80, 0xd7, - 0x0a, 0xf9, 0x19, 0x0f, 0x23, 0xde, 0xad, 0x8b, 0xad, 0x24, 0xc8, 0x1e, 0x42, 0xe3, 0xc8, 0xb4, - 0x78, 0x3c, 0x0a, 0xcc, 0xd0, 0x1c, 0x77, 0xd5, 0x6c, 0xa1, 0x2d, 0x44, 0xef, 0x23, 0x36, 0x32, - 0xe0, 0x28, 0x05, 0xd8, 0x47, 0xd0, 0x22, 0x28, 0x1a, 0x1d, 0x39, 0x6e, 0xcc, 0xc3, 0xae, 0x46, - 0x73, 0xda, 0x34, 0x87, 0x30, 0xc3, 0x90, 0x73, 0xa3, 0x29, 0x06, 0x09, 0x0c, 0xbb, 0x05, 0xc0, - 0xcf, 0x03, 0xd3, 0xb3, 0x47, 0xa6, 0xeb, 0x76, 0x81, 0xce, 0xa0, 0x09, 0xcc, 0x9a, 0xeb, 0xb2, - 0x37, 0xf1, 0x7c, 0xa6, 0x3d, 0x8a, 0xa3, 0x6e, 0x6b, 0x49, 0x59, 0xae, 0x18, 0x35, 0x04, 0x87, - 0x11, 0xd2, 0xd5, 0x32, 0xad, 0x13, 0xde, 0x6d, 0x2f, 0x29, 0xcb, 0x55, 0x43, 0x00, 0x88, 0x3d, - 0x72, 0xc2, 0x28, 0xee, 0xce, 0x0b, 0x2c, 0x01, 0xec, 0x06, 0xd4, 0xfc, 0xa3, 0xa3, 0x88, 0xc7, - 0xdd, 0x0e, 0xa1, 0x25, 0xa4, 0xaf, 0x82, 0x46, 0x5c, 0x45, 0x54, 0xbb, 0x03, 0xb5, 0x33, 0x04, - 0x04, 0xf3, 0x35, 0x56, 0x5b, 0x78, 0xec, 0x94, 0xf1, 0x0c, 0xd9, 0xa9, 0xdf, 0x06, 0x75, 0xc7, - 0xf4, 0x8e, 0x13, 0x6e, 0xc5, 0xe7, 0xa4, 0x09, 0x9a, 0x41, 0x6d, 0xfd, 0x0f, 0x4b, 0x50, 0x33, - 0x78, 0x34, 0x71, 0x63, 0xf6, 0x3e, 0x00, 0x3e, 0xd6, 0xd8, 0x8c, 0x43, 0xe7, 0x5c, 0xae, 0x9a, - 0x3d, 0x97, 0x36, 0x71, 0xec, 0xa7, 0xd4, 0xc5, 0x1e, 0x42, 0x93, 0x56, 0x4f, 0x86, 0x96, 0xb2, - 0x03, 0xa4, 0xe7, 0x33, 0x1a, 0x34, 0x44, 0xce, 0xb8, 0x01, 0x35, 0xe2, 0x0f, 0xc1, 0xa3, 0x2d, - 0x43, 0x42, 0xec, 0x0e, 0xb4, 0x1d, 0x2f, 0xc6, 0xf7, 0xb3, 0xe2, 0x91, 0xcd, 0xa3, 0x84, 0x81, - 0x5a, 0x29, 0x76, 0x93, 0x47, 0x31, 0x7b, 0x04, 0xe2, 0x11, 0x92, 0x0d, 0xab, 0xb4, 0x61, 0x3b, - 0x7d, 0xdc, 0x48, 0xec, 0x48, 0x63, 0xe4, 0x8e, 0xf7, 0xa1, 0x81, 0xf7, 0x4b, 0x66, 0xd4, 0x68, - 0x46, 0x93, 0x6e, 0x23, 0xc9, 0x61, 0x00, 0x0e, 0x90, 0xc3, 0x91, 0x34, 0xc8, 0xa4, 0x82, 0xa9, - 0xa8, 0xad, 0xf7, 0xa1, 0xba, 0x17, 0xda, 0x3c, 0x9c, 0x29, 0x27, 0x0c, 0x2a, 0x36, 0x8f, 0x2c, - 0x12, 0x61, 0xd5, 0xa0, 0x76, 0x26, 0x3b, 0xe5, 0x9c, 0xec, 0xe8, 0x7f, 0xa4, 0x40, 0x63, 0xe0, - 0x87, 0xf1, 0x53, 0x1e, 0x45, 0xe6, 0x31, 0x67, 0x8b, 0x50, 0xf5, 0x71, 0x59, 0x49, 0x61, 0x0d, - 0xcf, 0x44, 0xfb, 0x18, 0x02, 0x3f, 0xf5, 0x0e, 0xa5, 0xab, 0xdf, 0x01, 0x79, 0x8a, 0xa4, 0xae, - 0x2c, 0x79, 0x8a, 0x64, 0x2e, 0xe3, 0x9e, 0x4a, 0x9e, 0x7b, 0xae, 0x64, 0x4d, 0xfd, 0xdb, 0x00, - 0x78, 0xbe, 0xd7, 0xe4, 0x02, 0xfd, 0x17, 0x0a, 0x34, 0x0c, 0xf3, 0x28, 0xde, 0xf0, 0xbd, 0x98, - 0x9f, 0xc7, 0xac, 0x0d, 0x25, 0xc7, 0x26, 0x1a, 0xd5, 0x8c, 0x92, 0x63, 0xe3, 0xe9, 0x8e, 0x43, - 0x7f, 0x12, 0x10, 0x89, 0x5a, 0x86, 0x00, 0x88, 0x96, 0xb6, 0x1d, 0xd2, 0x91, 0x91, 0x96, 0xb6, - 0x1d, 0xb2, 0x45, 0x68, 0x44, 0x9e, 0x19, 0x44, 0x27, 0x7e, 0x8c, 0xa7, 0xab, 0xd0, 0xe9, 0x20, - 0x41, 0x0d, 0x23, 0x14, 0x3a, 0x27, 0x1a, 0xb9, 0xdc, 0x0c, 0x3d, 0x1e, 0x92, 0x22, 0x51, 0x0d, - 0xcd, 0x89, 0x76, 0x04, 0x42, 0xff, 0x45, 0x19, 0x6a, 0x4f, 0xf9, 0xf8, 0x90, 0x87, 0x97, 0x0e, - 0xf1, 0x10, 0x54, 0xda, 0x77, 0xe4, 0xd8, 0xe2, 0x1c, 0xeb, 0x6f, 0xbc, 0x78, 0xbe, 0xb8, 0x40, - 0xb8, 0x6d, 0xfb, 0x43, 0x7f, 0xec, 0xc4, 0x7c, 0x1c, 0xc4, 0x17, 0x46, 0x5d, 0xa2, 0x66, 0x1e, - 0xf0, 0x06, 0xd4, 0x5c, 0x6e, 0xe2, 0x9b, 0x09, 0xf6, 0x94, 0x10, 0xbb, 0x0f, 0x75, 0x73, 0x3c, - 0xb2, 0xb9, 0x69, 0x8b, 0x43, 0xad, 0x5f, 0x7f, 0xf1, 0x7c, 0xb1, 0x63, 0x8e, 0x37, 0xb9, 0x99, - 0x5f, 0xbb, 0x26, 0x30, 0xec, 0x13, 0xe4, 0xc9, 0x28, 0x1e, 0x4d, 0x02, 0xdb, 0x8c, 0x39, 0xe9, - 0xba, 0xca, 0x7a, 0xf7, 0xc5, 0xf3, 0xc5, 0xeb, 0x88, 0x3e, 0x20, 0x6c, 0x6e, 0x1a, 0x64, 0x58, - 0xd4, 0x7b, 0xc9, 0xf5, 0xa5, 0xde, 0x93, 0x20, 0xdb, 0x86, 0x05, 0xcb, 0x9d, 0x44, 0xa8, 0x9c, - 0x1d, 0xef, 0xc8, 0x1f, 0xf9, 0x9e, 0x7b, 0x41, 0x0f, 0xac, 0xae, 0xdf, 0x7a, 0xf1, 0x7c, 0xf1, - 0x5b, 0xb2, 0x73, 0xdb, 0x3b, 0xf2, 0xf7, 0x3c, 0xf7, 0x22, 0xb7, 0xfe, 0xfc, 0x54, 0x17, 0xfb, - 0xff, 0xd0, 0x3e, 0xf2, 0x43, 0x8b, 0x8f, 0x52, 0x92, 0xb5, 0x69, 0x9d, 0xde, 0x8b, 0xe7, 0x8b, - 0x37, 0xa8, 0xe7, 0xf1, 0x25, 0xba, 0x35, 0xf3, 0x78, 0xfd, 0x9f, 0x4b, 0x50, 0xa5, 0x36, 0x7b, - 0x08, 0xf5, 0x31, 0x3d, 0x49, 0xa2, 0x9f, 0x6e, 0x20, 0x0f, 0x51, 0xdf, 0x8a, 0x78, 0xab, 0xa8, - 0xef, 0xc5, 0xe1, 0x85, 0x91, 0x0c, 0xc3, 0x19, 0xb1, 0x79, 0xe8, 0xf2, 0x38, 0x92, 0x3c, 0x9f, - 0x9b, 0x31, 0x14, 0x1d, 0x72, 0x86, 0x1c, 0x36, 0xcd, 0x37, 0xe5, 0x4b, 0x7c, 0xd3, 0x03, 0xd5, - 0x3a, 0xe1, 0xd6, 0x69, 0x34, 0x19, 0x4b, 0xae, 0x4a, 0x61, 0xf6, 0x0e, 0xb4, 0xa8, 0x1d, 0xf8, - 0x8e, 0x47, 0xd3, 0xab, 0x34, 0xa0, 0x99, 0x21, 0x87, 0x51, 0x6f, 0x0b, 0x9a, 0xf9, 0xc3, 0xa2, - 0x39, 0x3f, 0xe5, 0x17, 0xc4, 0x5f, 0x15, 0x03, 0x9b, 0x6c, 0x09, 0xaa, 0xa4, 0xe8, 0x88, 0xbb, - 0x1a, 0xab, 0x80, 0x67, 0x16, 0x53, 0x0c, 0xd1, 0xf1, 0x69, 0xe9, 0xbb, 0x0a, 0xae, 0x93, 0xbf, - 0x42, 0x7e, 0x1d, 0xed, 0xea, 0x75, 0xc4, 0x94, 0xdc, 0x3a, 0xba, 0x0f, 0xf5, 0x1d, 0xc7, 0xe2, - 0x5e, 0x44, 0x46, 0x7f, 0x12, 0xf1, 0x54, 0x29, 0x61, 0x1b, 0xef, 0x3b, 0x36, 0xcf, 0x77, 0x7d, - 0x9b, 0x47, 0xb4, 0x4e, 0xc5, 0x48, 0x61, 0xec, 0xe3, 0xe7, 0x81, 0x13, 0x5e, 0x0c, 0x05, 0xa5, - 0xca, 0x46, 0x0a, 0x23, 0x77, 0x71, 0x0f, 0x37, 0xb3, 0x13, 0x03, 0x2e, 0x41, 0xfd, 0xcf, 0x2a, - 0xd0, 0xfc, 0x09, 0x0f, 0xfd, 0xfd, 0xd0, 0x0f, 0xfc, 0xc8, 0x74, 0xd9, 0x5a, 0x91, 0xe6, 0xe2, - 0x6d, 0x97, 0xf0, 0xb4, 0xf9, 0x61, 0x2b, 0x83, 0xf4, 0x11, 0xc4, 0x9b, 0xe5, 0x5f, 0x45, 0x87, - 0x9a, 0x78, 0xf3, 0x19, 0x34, 0x93, 0x3d, 0x38, 0x46, 0xbc, 0x32, 0x9d, 0xb5, 0x48, 0x0f, 0xd9, - 0x83, 0x52, 0x39, 0x36, 0xcf, 0x0f, 0xb6, 0x37, 0xe5, 0xdb, 0x4a, 0x48, 0x52, 0x61, 0x78, 0xee, - 0x0d, 0x93, 0x47, 0x4d, 0x61, 0xbc, 0x29, 0x52, 0x24, 0xda, 0xde, 0xec, 0x36, 0xa9, 0x2b, 0x01, - 0xd9, 0x5b, 0xa0, 0x8d, 0xcd, 0x73, 0x54, 0x68, 0xdb, 0xb6, 0x10, 0x4d, 0x23, 0x43, 0xb0, 0xb7, - 0xa1, 0x1c, 0x9f, 0x7b, 0x24, 0x7b, 0xe8, 0x55, 0xa0, 0x93, 0x39, 0x3c, 0xf7, 0xa4, 0xea, 0x33, - 0xb0, 0x0f, 0xdf, 0xd4, 0x72, 0x6c, 0x72, 0x22, 0x34, 0x03, 0x9b, 0xec, 0x0e, 0xd4, 0x5d, 0xf1, - 0x5a, 0xe4, 0x28, 0x34, 0x56, 0x1b, 0x42, 0x8f, 0x12, 0xca, 0x48, 0xfa, 0xd8, 0x87, 0xa0, 0x26, - 0xd4, 0xe9, 0x36, 0x68, 0x5c, 0x27, 0xa1, 0x67, 0x42, 0x46, 0x23, 0x1d, 0xc1, 0x1e, 0x82, 0x66, - 0x73, 0x97, 0xc7, 0x7c, 0xe4, 0x09, 0x45, 0xde, 0x10, 0x0e, 0xe4, 0x26, 0x21, 0x77, 0x23, 0x83, - 0xff, 0x6c, 0xc2, 0xa3, 0xd8, 0x50, 0x6d, 0x89, 0x60, 0xef, 0x66, 0x82, 0xd5, 0xa6, 0xe7, 0xca, - 0x13, 0x33, 0xe9, 0xea, 0x7d, 0x1f, 0xe6, 0xa7, 0x1e, 0x2d, 0xcf, 0xa5, 0x2d, 0xc1, 0xa5, 0xd7, - 0xf3, 0x5c, 0x5a, 0xc9, 0x71, 0xe6, 0xe7, 0x15, 0x55, 0xed, 0x68, 0xfa, 0x7f, 0x94, 0x61, 0x5e, - 0x0a, 0xcc, 0x89, 0x13, 0x0c, 0x62, 0xa9, 0xba, 0xc8, 0x30, 0x49, 0x5e, 0xad, 0x18, 0x09, 0xc8, - 0xfe, 0x1f, 0xd4, 0x48, 0xd3, 0x24, 0x02, 0xbf, 0x98, 0x31, 0x42, 0x3a, 0x5d, 0x28, 0x00, 0xc9, - 0x45, 0x72, 0x38, 0xfb, 0x18, 0xaa, 0x5f, 0xf0, 0xd0, 0x17, 0x86, 0xb6, 0xb1, 0x7a, 0x7b, 0xd6, - 0x3c, 0x24, 0x9f, 0x9c, 0x26, 0x06, 0xff, 0x4f, 0xf9, 0x05, 0x5e, 0x87, 0x5f, 0xde, 0x45, 0x63, - 0x3b, 0xf6, 0xcf, 0xb8, 0xdd, 0xad, 0x67, 0x34, 0x97, 0x4c, 0x9e, 0x74, 0x25, 0x2c, 0xa3, 0xce, - 0x64, 0x19, 0xed, 0x6a, 0x96, 0xe9, 0x6d, 0x42, 0x23, 0x47, 0x97, 0x19, 0x0f, 0xb5, 0x58, 0x54, - 0x27, 0x5a, 0xaa, 0x4a, 0xf3, 0x5a, 0x69, 0x13, 0x20, 0xa3, 0xd2, 0x37, 0xd5, 0x6d, 0xfa, 0xef, - 0x28, 0x30, 0xbf, 0xe1, 0x7b, 0x1e, 0x27, 0x57, 0x5d, 0xbc, 0x79, 0x26, 0xe2, 0xca, 0x95, 0x22, - 0xfe, 0x01, 0x54, 0x23, 0x1c, 0x2c, 0x57, 0xbf, 0x36, 0xe3, 0x11, 0x0d, 0x31, 0x02, 0x15, 0xfd, - 0xd8, 0x3c, 0x1f, 0x05, 0xdc, 0xb3, 0x1d, 0xef, 0x38, 0x51, 0xf4, 0x63, 0xf3, 0x7c, 0x5f, 0x60, - 0xf4, 0xbf, 0x2a, 0x01, 0x7c, 0xc6, 0x4d, 0x37, 0x3e, 0x41, 0x63, 0x86, 0x2f, 0xea, 0x78, 0x51, - 0x6c, 0x7a, 0x56, 0x12, 0x28, 0xa5, 0x30, 0xbe, 0x28, 0xda, 0x74, 0x1e, 0x09, 0x15, 0xa9, 0x19, - 0x09, 0x88, 0xfc, 0x81, 0xdb, 0x4d, 0x22, 0x69, 0xfb, 0x25, 0x94, 0x39, 0x32, 0x15, 0x42, 0x4b, - 0x47, 0xa6, 0x0b, 0x75, 0x0c, 0x3c, 0x1c, 0xdf, 0x23, 0xa6, 0xd1, 0x8c, 0x04, 0xc4, 0x75, 0x26, - 0x41, 0xec, 0x8c, 0x85, 0x85, 0x2f, 0x1b, 0x12, 0xc2, 0x53, 0xa1, 0x45, 0xef, 0x5b, 0x27, 0x3e, - 0x29, 0x92, 0xb2, 0x91, 0xc2, 0xb8, 0x9a, 0xef, 0x1d, 0xfb, 0x78, 0x3b, 0x95, 0x9c, 0xc7, 0x04, - 0x14, 0x77, 0xb1, 0xf9, 0x39, 0x76, 0x69, 0xd4, 0x95, 0xc2, 0x48, 0x17, 0xce, 0x47, 0x47, 0xdc, - 0x8c, 0x27, 0x21, 0x8f, 0xba, 0x40, 0xdd, 0xc0, 0xf9, 0x96, 0xc4, 0xb0, 0xb7, 0xa1, 0x89, 0x84, - 0x33, 0xa3, 0xc8, 0x39, 0xf6, 0xb8, 0x4d, 0xea, 0xa5, 0x62, 0x20, 0x31, 0xd7, 0x24, 0x4a, 0xff, - 0x9b, 0x12, 0xd4, 0x84, 0x2e, 0x28, 0x38, 0x4b, 0xca, 0x2b, 0x39, 0x4b, 0x6f, 0x81, 0x16, 0x84, - 0xdc, 0x76, 0xac, 0xe4, 0x1d, 0x35, 0x23, 0x43, 0x50, 0x74, 0x83, 0xde, 0x01, 0xd1, 0x53, 0x35, - 0x04, 0xc0, 0x74, 0x68, 0xf9, 0xde, 0xc8, 0x76, 0xa2, 0xd3, 0xd1, 0xe1, 0x45, 0xcc, 0x23, 0x49, - 0x8b, 0x86, 0xef, 0x6d, 0x3a, 0xd1, 0xe9, 0x3a, 0xa2, 0x90, 0x84, 0x42, 0x46, 0x48, 0x36, 0x54, - 0x43, 0x42, 0xec, 0x23, 0xd0, 0xc8, 0x87, 0x25, 0x27, 0x47, 0x23, 0xe7, 0xe4, 0xc6, 0x8b, 0xe7, - 0x8b, 0x0c, 0x91, 0x53, 0xde, 0x8d, 0x9a, 0xe0, 0xd0, 0x4b, 0xc3, 0xc9, 0x68, 0xae, 0x48, 0x86, - 0x85, 0x97, 0x86, 0xa8, 0x61, 0x94, 0xf7, 0xd2, 0x04, 0x86, 0xdd, 0x07, 0x36, 0xf1, 0x2c, 0x7f, - 0x1c, 0x20, 0x53, 0x70, 0x5b, 0x1e, 0xb2, 0x41, 0x87, 0x5c, 0xc8, 0xf7, 0xd0, 0x51, 0xf5, 0x7f, - 0x2a, 0x41, 0x73, 0xd3, 0x09, 0xb9, 0x15, 0x73, 0xbb, 0x6f, 0x1f, 0x73, 0x3c, 0x3b, 0xf7, 0x62, - 0x27, 0xbe, 0x90, 0x6e, 0xa8, 0x84, 0xd2, 0x28, 0xa2, 0x54, 0x8c, 0xb6, 0x85, 0x84, 0x95, 0x29, - 0x41, 0x20, 0x00, 0xb6, 0x0a, 0x20, 0xe2, 0x2b, 0x4a, 0x12, 0x54, 0xae, 0x4e, 0x12, 0x68, 0x34, - 0x0c, 0x9b, 0x18, 0x84, 0x8b, 0x39, 0x8e, 0xf0, 0x45, 0x6b, 0x94, 0x41, 0x98, 0x70, 0xe1, 0xd1, - 0x52, 0xd8, 0x57, 0x17, 0x1b, 0x63, 0x9b, 0xbd, 0x03, 0x25, 0x3f, 0x20, 0xe2, 0xca, 0xa5, 0xf3, - 0x57, 0x58, 0xd9, 0x0b, 0x8c, 0x92, 0x1f, 0xa0, 0x14, 0x8b, 0xd8, 0x97, 0x18, 0x0f, 0xa5, 0x18, - 0xed, 0x1e, 0x45, 0x5c, 0x86, 0xec, 0x61, 0x3a, 0x34, 0x4d, 0xd7, 0xf5, 0x7f, 0xce, 0xed, 0xfd, - 0x90, 0xdb, 0x09, 0x0f, 0x16, 0x70, 0xc8, 0x25, 0x9e, 0x39, 0xe6, 0x51, 0x60, 0x5a, 0x5c, 0xb2, - 0x60, 0x86, 0xd0, 0x6f, 0x40, 0x69, 0x2f, 0x60, 0x75, 0x28, 0x0f, 0xfa, 0xc3, 0xce, 0x1c, 0x36, - 0x36, 0xfb, 0x3b, 0x1d, 0xb4, 0x28, 0xb5, 0x4e, 0x5d, 0xff, 0xb2, 0x04, 0xda, 0xd3, 0x49, 0x6c, - 0xa2, 0x6e, 0x89, 0xf0, 0x96, 0x45, 0x0e, 0xcd, 0x58, 0xf1, 0x5b, 0xa0, 0x46, 0xb1, 0x19, 0x92, - 0x57, 0x22, 0xac, 0x53, 0x9d, 0xe0, 0x61, 0xc4, 0xde, 0x83, 0x2a, 0xb7, 0x8f, 0x79, 0x62, 0x2e, - 0x3a, 0xd3, 0xf7, 0x35, 0x44, 0x37, 0x5b, 0x86, 0x5a, 0x64, 0x9d, 0xf0, 0xb1, 0xd9, 0xad, 0x64, - 0x03, 0x07, 0x84, 0x11, 0x6e, 0xb8, 0x21, 0xfb, 0xd9, 0xbb, 0x50, 0xc5, 0xb7, 0x89, 0x64, 0x5c, - 0x49, 0x91, 0x28, 0x3e, 0x83, 0x1c, 0x26, 0x3a, 0x91, 0xf1, 0xec, 0xd0, 0x0f, 0x46, 0x7e, 0x40, - 0xb4, 0x6f, 0xaf, 0x5e, 0x27, 0x1d, 0x97, 0xdc, 0x66, 0x65, 0x33, 0xf4, 0x83, 0xbd, 0xc0, 0xa8, - 0xd9, 0xf4, 0x8b, 0x51, 0x0e, 0x0d, 0x17, 0x1c, 0x21, 0x8c, 0x82, 0x86, 0x18, 0x91, 0x4a, 0x5a, - 0x06, 0x75, 0xcc, 0x63, 0xd3, 0x36, 0x63, 0x53, 0xda, 0x86, 0xa6, 0x50, 0x99, 0x02, 0x67, 0xa4, - 0xbd, 0xfa, 0x03, 0xa8, 0x89, 0xa5, 0x99, 0x0a, 0x95, 0xdd, 0xbd, 0xdd, 0xbe, 0x20, 0xeb, 0xda, - 0xce, 0x4e, 0x47, 0x41, 0xd4, 0xe6, 0xda, 0x70, 0xad, 0x53, 0xc2, 0xd6, 0xf0, 0xc7, 0xfb, 0xfd, - 0x4e, 0x59, 0xff, 0x7b, 0x05, 0xd4, 0x64, 0x1d, 0xf6, 0x29, 0x00, 0x8a, 0xf0, 0xe8, 0xc4, 0xf1, - 0x52, 0x07, 0xef, 0x66, 0x7e, 0xa7, 0x15, 0x7c, 0xd5, 0xcf, 0xb0, 0x57, 0x98, 0x57, 0x92, 0x78, - 0x82, 0x7b, 0x03, 0x68, 0x17, 0x3b, 0x67, 0x78, 0xba, 0xf7, 0xf2, 0x56, 0xa5, 0xbd, 0xfa, 0x46, - 0x61, 0x69, 0x9c, 0x49, 0xac, 0x9d, 0x33, 0x30, 0xf7, 0x41, 0x4d, 0xd0, 0xac, 0x01, 0xf5, 0xcd, - 0xfe, 0xd6, 0xda, 0xc1, 0x0e, 0xb2, 0x0a, 0x40, 0x6d, 0xb0, 0xbd, 0xfb, 0x78, 0xa7, 0x2f, 0xae, - 0xb5, 0xb3, 0x3d, 0x18, 0x76, 0x4a, 0xfa, 0x1f, 0x28, 0xa0, 0x26, 0x9e, 0x0c, 0xfb, 0x00, 0x9d, - 0x0f, 0x72, 0xd2, 0xa4, 0x25, 0xa2, 0x8c, 0x50, 0x2e, 0x6c, 0x35, 0x92, 0x7e, 0x94, 0x45, 0x52, - 0xac, 0x89, 0x6f, 0x43, 0x40, 0x3e, 0x6a, 0x2e, 0x17, 0x12, 0x3a, 0x0c, 0x2a, 0xb6, 0xef, 0x71, - 0xe9, 0x30, 0x53, 0x9b, 0x78, 0xd0, 0xf1, 0x2c, 0x9e, 0x85, 0x13, 0x75, 0x82, 0x87, 0x91, 0x1e, - 0x0b, 0x3f, 0x3a, 0x3d, 0x58, 0xba, 0x9b, 0x92, 0xdf, 0xed, 0x52, 0x50, 0x52, 0xba, 0x1c, 0x94, - 0x64, 0x86, 0xb3, 0xfa, 0x75, 0x86, 0x53, 0xff, 0xe3, 0x2a, 0xb4, 0x0d, 0x1e, 0xc5, 0x7e, 0xc8, - 0xa5, 0x5f, 0xf8, 0x32, 0x11, 0xba, 0x05, 0x10, 0x8a, 0xc1, 0xd9, 0xd6, 0x9a, 0xc4, 0x88, 0x68, - 0xca, 0xf5, 0x2d, 0xe2, 0x5d, 0x69, 0x21, 0x53, 0x98, 0xdd, 0x04, 0xed, 0xd0, 0xb4, 0x4e, 0xc5, - 0xb2, 0xc2, 0x4e, 0xaa, 0x02, 0x21, 0xd6, 0x35, 0x2d, 0x8b, 0x47, 0xd1, 0x08, 0x59, 0x41, 0x58, - 0x4b, 0x4d, 0x60, 0x9e, 0xf0, 0x0b, 0xf6, 0x10, 0x20, 0xe2, 0x56, 0xc8, 0x63, 0xea, 0x46, 0x9b, - 0xa9, 0xad, 0x2f, 0xfc, 0xea, 0xf9, 0xe2, 0xdc, 0x3f, 0x3e, 0x5f, 0xd4, 0x06, 0xdc, 0x8b, 0x9c, - 0xd8, 0x39, 0xe3, 0x86, 0x26, 0x06, 0xe1, 0x8c, 0xef, 0x40, 0x2b, 0xe2, 0x11, 0x1a, 0xdb, 0x51, - 0xec, 0x9f, 0x72, 0xe1, 0x97, 0xcf, 0x9c, 0xd4, 0x94, 0xe3, 0x86, 0x38, 0x0c, 0x15, 0x91, 0xe9, - 0xf9, 0xde, 0xc5, 0xd8, 0x9f, 0x44, 0xd2, 0xb2, 0x64, 0x08, 0xb6, 0x02, 0xd7, 0xb8, 0x67, 0x85, - 0x17, 0x01, 0xde, 0x08, 0xcf, 0x32, 0x3a, 0x72, 0x5c, 0x2e, 0x1d, 0xfa, 0x85, 0xac, 0xeb, 0x09, - 0xbf, 0xd8, 0x72, 0x5c, 0x8e, 0xd7, 0x3a, 0x33, 0x27, 0x6e, 0x3c, 0xa2, 0x7c, 0x01, 0x88, 0x6b, - 0x11, 0x66, 0xcd, 0xb6, 0x43, 0x76, 0x17, 0x16, 0x44, 0x77, 0xe8, 0xbb, 0xdc, 0xb1, 0xc5, 0x62, - 0x0d, 0x1a, 0x35, 0x4f, 0x1d, 0x06, 0xe1, 0x69, 0xa9, 0x15, 0xb8, 0x26, 0xc6, 0x8a, 0x3b, 0x26, - 0xa3, 0x9b, 0x62, 0x6b, 0xea, 0x1a, 0xc8, 0x9e, 0xe2, 0xd6, 0x81, 0x19, 0x9f, 0x50, 0x14, 0x90, - 0x6c, 0xbd, 0x6f, 0xc6, 0x27, 0xe8, 0x17, 0x88, 0xee, 0x23, 0x87, 0xbb, 0x22, 0x8a, 0xd7, 0x0c, - 0x31, 0x63, 0x0b, 0x31, 0xe8, 0x17, 0xc8, 0x01, 0x7e, 0x38, 0x36, 0x45, 0xfa, 0x51, 0x33, 0xc4, - 0xa4, 0x2d, 0x42, 0xe1, 0x16, 0xf2, 0x45, 0xbd, 0xc9, 0x98, 0x12, 0x91, 0x15, 0x43, 0xbe, 0xf1, - 0xee, 0x64, 0xcc, 0x3e, 0x80, 0x8e, 0xe3, 0x59, 0x21, 0x1f, 0x73, 0x2f, 0x36, 0xdd, 0xd1, 0x51, - 0xe8, 0x8f, 0xbb, 0x0b, 0x34, 0x68, 0x3e, 0x87, 0xdf, 0x0a, 0xfd, 0xb1, 0xcc, 0xde, 0x04, 0x66, - 0x18, 0x3b, 0xa6, 0xdb, 0x65, 0x49, 0xf6, 0x66, 0x5f, 0x20, 0xf4, 0x17, 0x65, 0x50, 0xd3, 0xf0, - 0xf2, 0x1e, 0x68, 0xe3, 0x44, 0x3f, 0x4a, 0xc7, 0xb0, 0x55, 0x50, 0x9a, 0x46, 0xd6, 0xcf, 0x6e, - 0x41, 0xe9, 0xf4, 0x4c, 0xea, 0xea, 0xd6, 0x8a, 0x48, 0xec, 0x07, 0x87, 0x1f, 0xaf, 0x3c, 0x79, - 0x66, 0x94, 0x4e, 0xcf, 0x5e, 0x43, 0x4e, 0xd8, 0xfb, 0x30, 0x6f, 0xb9, 0xdc, 0xf4, 0x46, 0x99, - 0x37, 0x43, 0x7c, 0x68, 0xb4, 0x09, 0xbd, 0x9f, 0xba, 0x34, 0x77, 0xa0, 0x6a, 0x73, 0x37, 0x36, - 0xf3, 0xf9, 0xe5, 0xbd, 0xd0, 0xb4, 0x5c, 0xbe, 0x89, 0x68, 0x43, 0xf4, 0xa2, 0xae, 0x4e, 0x43, - 0xba, 0x9c, 0xae, 0x9e, 0x11, 0xce, 0xa5, 0x7a, 0x00, 0xf2, 0x7a, 0xe0, 0x1e, 0x2c, 0xf0, 0xf3, - 0x80, 0x0c, 0xd4, 0x28, 0xcd, 0x60, 0x08, 0xcb, 0xd9, 0x49, 0x3a, 0x36, 0x92, 0x4c, 0xc6, 0x87, - 0xa8, 0xa2, 0x48, 0x48, 0x89, 0x61, 0x1a, 0xab, 0x8c, 0x74, 0x5c, 0x41, 0xec, 0x8d, 0x64, 0x08, - 0xfb, 0x00, 0x34, 0xcb, 0xb6, 0x46, 0x82, 0x32, 0xad, 0xec, 0x6c, 0x1b, 0x9b, 0x1b, 0x82, 0x24, - 0xaa, 0x65, 0x5b, 0xc2, 0x8b, 0x2f, 0x84, 0x9a, 0xed, 0x57, 0x09, 0x35, 0xf3, 0x46, 0xb8, 0x53, - 0x30, 0xc2, 0x9f, 0x57, 0xd4, 0x7a, 0x47, 0xd5, 0xdf, 0x01, 0x35, 0xd9, 0x08, 0x55, 0x6b, 0xc4, - 0x3d, 0x99, 0x46, 0x20, 0xd5, 0x8a, 0xe0, 0x30, 0xd2, 0x2d, 0x28, 0x3f, 0x79, 0x36, 0x20, 0x0d, - 0x8b, 0xc6, 0xae, 0x4a, 0xbe, 0x11, 0xb5, 0x53, 0xad, 0x5b, 0xca, 0x69, 0xdd, 0xdb, 0xc2, 0x60, - 0xd1, 0x03, 0x25, 0xb9, 0xd7, 0x1c, 0x06, 0x49, 0x2c, 0x8c, 0x75, 0x45, 0xa4, 0x65, 0x09, 0xd0, - 0xff, 0xad, 0x0c, 0x75, 0xe9, 0x4f, 0xa1, 0x91, 0x9a, 0xa4, 0x69, 0x43, 0x6c, 0x16, 0x03, 0xdd, - 0xd4, 0x31, 0xcb, 0xd7, 0x6e, 0xca, 0x5f, 0x5f, 0xbb, 0x61, 0x9f, 0x42, 0x33, 0x10, 0x7d, 0x79, - 0x57, 0xee, 0xcd, 0xfc, 0x1c, 0xf9, 0x4b, 0xf3, 0x1a, 0x41, 0x06, 0x20, 0x29, 0x29, 0x81, 0x1d, - 0x9b, 0xc7, 0x92, 0x02, 0x75, 0x84, 0x87, 0xe6, 0xf1, 0x2b, 0xf9, 0x65, 0x6d, 0x72, 0xf0, 0x9a, - 0xa4, 0xe0, 0xd1, 0x97, 0xcb, 0xbf, 0x4c, 0xab, 0xe8, 0x1e, 0xdd, 0x04, 0xcd, 0xf2, 0xc7, 0x63, - 0x87, 0xfa, 0xda, 0x32, 0x4d, 0x46, 0x88, 0x61, 0xa4, 0xff, 0x9e, 0x02, 0x75, 0x79, 0xaf, 0x4b, - 0xc6, 0x77, 0x7d, 0x7b, 0x77, 0xcd, 0xf8, 0x71, 0x47, 0x41, 0xe7, 0x62, 0x7b, 0x77, 0xd8, 0x29, - 0x31, 0x0d, 0xaa, 0x5b, 0x3b, 0x7b, 0x6b, 0xc3, 0x4e, 0x19, 0x0d, 0xf2, 0xfa, 0xde, 0xde, 0x4e, - 0xa7, 0xc2, 0x9a, 0xa0, 0x6e, 0xae, 0x0d, 0xfb, 0xc3, 0xed, 0xa7, 0xfd, 0x4e, 0x15, 0xc7, 0x3e, - 0xee, 0xef, 0x75, 0x6a, 0xd8, 0x38, 0xd8, 0xde, 0xec, 0xd4, 0xb1, 0x7f, 0x7f, 0x6d, 0x30, 0xf8, - 0xe1, 0x9e, 0xb1, 0xd9, 0x51, 0xc9, 0xa8, 0x0f, 0x8d, 0xed, 0xdd, 0xc7, 0x1d, 0x0d, 0xdb, 0x7b, - 0xeb, 0x9f, 0xf7, 0x37, 0x86, 0x1d, 0xd0, 0x1f, 0x41, 0x23, 0x47, 0x2b, 0x9c, 0x6d, 0xf4, 0xb7, - 0x3a, 0x73, 0xb8, 0xe5, 0xb3, 0xb5, 0x9d, 0x03, 0xf4, 0x01, 0xda, 0x00, 0xd4, 0x1c, 0xed, 0xac, - 0xed, 0x3e, 0xee, 0x94, 0xa4, 0x07, 0xf9, 0x03, 0x50, 0x0f, 0x1c, 0x7b, 0xdd, 0xf5, 0xad, 0x53, - 0x64, 0x9f, 0x43, 0x33, 0xe2, 0x92, 0xdf, 0xa8, 0x8d, 0xfe, 0x3a, 0x09, 0x6d, 0x24, 0xdf, 0x5a, - 0x42, 0x48, 0x31, 0x6f, 0x32, 0x1e, 0x51, 0x7d, 0xaf, 0x2c, 0x0c, 0xa5, 0x37, 0x19, 0x1f, 0x38, - 0x76, 0xa4, 0x9f, 0x42, 0xfd, 0xc0, 0xb1, 0xf7, 0x4d, 0xeb, 0x94, 0xd4, 0x24, 0x2e, 0x3d, 0x8a, - 0x9c, 0x2f, 0xb8, 0x34, 0xa8, 0x1a, 0x61, 0x06, 0xce, 0x17, 0x9c, 0xbd, 0x0b, 0x35, 0x02, 0x92, - 0x14, 0x07, 0x89, 0x5a, 0x72, 0x1c, 0x43, 0xf6, 0x51, 0x79, 0xcd, 0x75, 0x7d, 0x6b, 0x14, 0xf2, - 0xa3, 0xee, 0x9b, 0xe2, 0x05, 0x08, 0x61, 0xf0, 0x23, 0xfd, 0xf7, 0x95, 0xf4, 0xe6, 0x54, 0xc5, - 0x59, 0x84, 0x4a, 0x60, 0x5a, 0xa7, 0xd2, 0x9f, 0x69, 0xc8, 0x05, 0xf1, 0x30, 0x06, 0x75, 0xb0, - 0xf7, 0x41, 0x95, 0x8c, 0x94, 0xec, 0xda, 0xc8, 0x71, 0x9c, 0x91, 0x76, 0x16, 0x1f, 0xbe, 0x5c, - 0x7c, 0x78, 0x8a, 0x86, 0x03, 0xd7, 0x89, 0x85, 0xd8, 0xa0, 0x70, 0x12, 0xa4, 0x7f, 0x0c, 0x90, - 0x15, 0xd4, 0x66, 0xb8, 0x77, 0xd7, 0xa1, 0x6a, 0xba, 0x8e, 0x99, 0x44, 0xd7, 0x02, 0xd0, 0x77, - 0xa1, 0x91, 0x2b, 0xc3, 0x21, 0x6d, 0x4d, 0xd7, 0x45, 0x1b, 0x2b, 0x64, 0x5f, 0x35, 0xea, 0xa6, - 0xeb, 0x3e, 0xe1, 0x17, 0x11, 0xba, 0xd6, 0xa2, 0x82, 0x57, 0x9a, 0x2a, 0xf2, 0xd0, 0x54, 0x43, - 0x74, 0xea, 0x1f, 0x42, 0x6d, 0x2b, 0x09, 0x40, 0x12, 0x61, 0x50, 0xae, 0x12, 0x06, 0xfd, 0x13, - 0x79, 0x66, 0xaa, 0x13, 0xb1, 0x7b, 0xb2, 0x52, 0x18, 0x89, 0xba, 0xa4, 0x92, 0xe5, 0x67, 0xc4, - 0x20, 0x59, 0x24, 0xa4, 0xc1, 0xfa, 0x26, 0xa8, 0x2f, 0xad, 0xbd, 0x4a, 0x02, 0x94, 0x32, 0x02, - 0xcc, 0xa8, 0xc6, 0xea, 0x3f, 0x05, 0xc8, 0x2a, 0x8a, 0x52, 0x36, 0xc5, 0x2a, 0x28, 0x9b, 0x77, - 0x41, 0xb5, 0x4e, 0x1c, 0xd7, 0x0e, 0xb9, 0x57, 0xb8, 0x75, 0x56, 0x83, 0x4c, 0xfb, 0xd9, 0x12, - 0x54, 0xa8, 0x50, 0x5a, 0xce, 0x34, 0x77, 0x5a, 0x25, 0xa5, 0x1e, 0xfd, 0x1c, 0x5a, 0x22, 0x66, - 0x79, 0x05, 0x8f, 0xaf, 0xa8, 0x3a, 0x4b, 0x97, 0x54, 0xe7, 0x0d, 0xa8, 0x91, 0x0b, 0x91, 0xdc, - 0x46, 0x42, 0x57, 0xa8, 0xd4, 0xdf, 0x2d, 0x01, 0x88, 0xad, 0x77, 0x7d, 0x9b, 0x17, 0x93, 0x03, - 0xca, 0x74, 0x72, 0x80, 0x41, 0x25, 0xad, 0x81, 0x6b, 0x06, 0xb5, 0x33, 0x63, 0x28, 0x13, 0x06, - 0xc2, 0x18, 0xbe, 0x05, 0x1a, 0x79, 0x79, 0xce, 0x17, 0x54, 0x80, 0xc1, 0x0d, 0x33, 0x44, 0xbe, - 0x22, 0x5c, 0x2d, 0x56, 0x84, 0xd3, 0xf2, 0x58, 0x4d, 0xac, 0x26, 0xca, 0x63, 0x33, 0x2a, 0x7d, - 0x22, 0x63, 0x13, 0xf1, 0x30, 0x4e, 0xd2, 0x0d, 0x02, 0x4a, 0x23, 0x67, 0x4d, 0x8e, 0x35, 0x45, - 0xce, 0xc5, 0xf3, 0x47, 0x96, 0xef, 0x1d, 0xb9, 0x8e, 0x15, 0xcb, 0x0a, 0x30, 0x78, 0xfe, 0x86, - 0xc4, 0xe8, 0x9f, 0x42, 0x33, 0xa1, 0x3f, 0x15, 0xd4, 0xee, 0xa6, 0x51, 0xa5, 0x92, 0xbd, 0x6d, - 0x46, 0xa6, 0xf5, 0x52, 0x57, 0x49, 0xe2, 0x4a, 0xfd, 0x3f, 0xcb, 0xc9, 0x64, 0x59, 0xf7, 0x79, - 0x39, 0x0d, 0x8b, 0x89, 0x82, 0xd2, 0x2b, 0x25, 0x0a, 0xbe, 0x0b, 0x9a, 0x4d, 0xb1, 0xaf, 0x73, - 0x96, 0x18, 0xb1, 0xde, 0x74, 0x9c, 0x2b, 0xa3, 0x63, 0xf2, 0xba, 0xd3, 0xc1, 0x5f, 0xf3, 0x0e, - 0x29, 0xb5, 0xab, 0xb3, 0xa8, 0x5d, 0xfb, 0x86, 0xd4, 0x7e, 0x1b, 0x9a, 0x9e, 0xef, 0x8d, 0xbc, - 0x89, 0xeb, 0x9a, 0x87, 0x2e, 0x97, 0xe4, 0x6e, 0x78, 0xbe, 0xb7, 0x2b, 0x51, 0xe8, 0x67, 0xe7, - 0x87, 0x08, 0xa1, 0x6e, 0xd0, 0xb8, 0xf9, 0xdc, 0x38, 0x12, 0xfd, 0x65, 0xe8, 0xf8, 0x87, 0x3f, - 0xe5, 0x56, 0x4c, 0x14, 0x1b, 0x91, 0x34, 0x0b, 0x27, 0xbb, 0x2d, 0xf0, 0x48, 0xa2, 0x5d, 0x94, - 0xeb, 0xa9, 0x67, 0x6e, 0x5d, 0x7a, 0xe6, 0x4f, 0x40, 0x4b, 0xa9, 0x94, 0x8b, 0xb3, 0x35, 0xa8, - 0x6e, 0xef, 0x6e, 0xf6, 0x7f, 0xd4, 0x51, 0xd0, 0x5c, 0x1a, 0xfd, 0x67, 0x7d, 0x63, 0xd0, 0xef, - 0x94, 0xd0, 0x94, 0x6d, 0xf6, 0x77, 0xfa, 0xc3, 0x7e, 0xa7, 0x2c, 0x5c, 0x21, 0x2a, 0xbf, 0xb8, - 0x8e, 0xe5, 0xc4, 0xfa, 0x00, 0x20, 0x4b, 0x1e, 0xa0, 0x56, 0xce, 0x0e, 0x27, 0xb3, 0x97, 0x71, - 0x72, 0xac, 0xe5, 0x54, 0x20, 0x4b, 0x57, 0xa5, 0x28, 0x44, 0xbf, 0xbe, 0x0a, 0xda, 0x53, 0x33, - 0xf8, 0x4c, 0x14, 0x2a, 0xef, 0x40, 0x9b, 0xfc, 0xef, 0x24, 0xb2, 0x11, 0xca, 0xb2, 0x69, 0xb4, - 0x52, 0x2c, 0xea, 0x5e, 0xfd, 0xcf, 0x15, 0xb8, 0xfe, 0xd4, 0x3f, 0xe3, 0xa9, 0xbf, 0xbb, 0x6f, - 0x5e, 0xb8, 0xbe, 0x69, 0x7f, 0x0d, 0x1b, 0xde, 0x02, 0x88, 0xfc, 0x09, 0x15, 0x0e, 0x93, 0x32, - 0xab, 0xa1, 0x09, 0xcc, 0x63, 0xf9, 0x7d, 0x08, 0x8f, 0x62, 0xea, 0x94, 0x86, 0x14, 0x61, 0xec, - 0x7a, 0x03, 0x6a, 0xf1, 0xb9, 0x97, 0x15, 0x7d, 0xab, 0x31, 0x65, 0xdd, 0x67, 0xba, 0xbf, 0xd5, - 0xd9, 0xee, 0xaf, 0xbe, 0x01, 0xda, 0xf0, 0x9c, 0xf2, 0xce, 0x93, 0xa2, 0x03, 0xaa, 0xbc, 0xc4, - 0xcd, 0x29, 0x4d, 0xb9, 0x39, 0xff, 0xaa, 0x40, 0x23, 0xe7, 0xc7, 0xb3, 0xb7, 0xa1, 0x12, 0x9f, - 0x7b, 0xc5, 0x6f, 0x2b, 0x92, 0x4d, 0x0c, 0xea, 0xba, 0x94, 0x5b, 0x2d, 0x5d, 0xca, 0xad, 0xb2, - 0x1d, 0x98, 0x17, 0x9a, 0x37, 0xb9, 0x44, 0x92, 0x82, 0x7a, 0x67, 0x2a, 0x6e, 0x10, 0xb9, 0xf9, - 0xe4, 0x4a, 0x32, 0xaf, 0xd2, 0x3e, 0x2e, 0x20, 0x7b, 0x6b, 0x70, 0x6d, 0xc6, 0xb0, 0xd7, 0xa9, - 0xd2, 0xe8, 0x8b, 0xd0, 0x1a, 0x9e, 0x7b, 0x43, 0x67, 0xcc, 0xa3, 0xd8, 0x1c, 0x07, 0xe4, 0x26, - 0x4a, 0xcb, 0x59, 0x31, 0x4a, 0x71, 0xa4, 0xbf, 0x07, 0xcd, 0x7d, 0xce, 0x43, 0x83, 0x47, 0x81, - 0xef, 0x09, 0xe7, 0x48, 0xe6, 0xc4, 0x85, 0x99, 0x96, 0x90, 0xfe, 0xdb, 0xa0, 0x19, 0xe6, 0x51, - 0xbc, 0x6e, 0xc6, 0xd6, 0xc9, 0xeb, 0x24, 0x59, 0xde, 0x83, 0x7a, 0x20, 0x78, 0x4a, 0x46, 0x77, - 0x4d, 0x32, 0xd7, 0x92, 0xcf, 0x8c, 0xa4, 0x53, 0xff, 0x0e, 0xb4, 0x65, 0x81, 0x2a, 0x39, 0x49, - 0xae, 0x8a, 0xa5, 0x5c, 0x59, 0xc5, 0xd2, 0x8f, 0xa1, 0x95, 0xcc, 0x13, 0xc6, 0xef, 0x95, 0xa6, - 0xbd, 0xfe, 0x67, 0x02, 0xfa, 0x6f, 0xc1, 0xb5, 0xc1, 0xe4, 0x30, 0xb2, 0x42, 0x87, 0x72, 0x02, - 0xc9, 0x76, 0x3d, 0x50, 0x83, 0x90, 0x1f, 0x39, 0xe7, 0x3c, 0x11, 0xb1, 0x14, 0x66, 0x77, 0xa1, - 0x3e, 0x46, 0x7a, 0xf1, 0x4c, 0x78, 0xb3, 0x98, 0xf5, 0x29, 0xf6, 0x18, 0xc9, 0x00, 0xfd, 0x7b, - 0x70, 0xbd, 0xb8, 0xbc, 0xa4, 0xc2, 0x3b, 0x50, 0x3e, 0x3d, 0x8b, 0x24, 0x99, 0x17, 0x0a, 0x31, - 0x2f, 0x7d, 0x9f, 0x81, 0xbd, 0xfa, 0x5f, 0x2b, 0x50, 0xc6, 0x18, 0x3d, 0xf7, 0xf1, 0x59, 0x45, - 0x7c, 0x7c, 0x76, 0x33, 0x9f, 0x3f, 0x17, 0x31, 0x54, 0x96, 0x27, 0x7f, 0x0b, 0xb4, 0x23, 0x3f, - 0xfc, 0xb9, 0x19, 0xda, 0xdc, 0x96, 0x16, 0x38, 0x43, 0x90, 0xeb, 0x3c, 0x19, 0x07, 0x52, 0xbd, - 0x53, 0x9b, 0xdd, 0x91, 0x36, 0x5c, 0xc4, 0x35, 0x0b, 0x48, 0xd9, 0xdd, 0xc9, 0x78, 0xc5, 0xe5, - 0x66, 0x44, 0xc6, 0x46, 0x98, 0x75, 0xfd, 0x1e, 0x68, 0x29, 0x0a, 0x15, 0xe4, 0xee, 0x60, 0xb4, - 0xbd, 0x29, 0x72, 0x92, 0x18, 0x01, 0x28, 0xa8, 0x1c, 0x87, 0x3f, 0xda, 0x1d, 0x0d, 0x07, 0x9d, - 0x92, 0xfe, 0x13, 0x68, 0x24, 0xf2, 0xb3, 0x6d, 0x53, 0x01, 0x8e, 0x04, 0x78, 0xdb, 0x2e, 0xc8, - 0xf3, 0x36, 0x85, 0x68, 0xdc, 0xb3, 0xb7, 0x13, 0xc1, 0x13, 0x40, 0xf1, 0x86, 0xb2, 0x9a, 0x97, - 0xdc, 0x50, 0xef, 0xc3, 0x82, 0x41, 0x85, 0x04, 0x34, 0xbc, 0xc9, 0x93, 0xdd, 0x80, 0x9a, 0xe7, - 0xdb, 0x3c, 0xdd, 0x40, 0x42, 0xb8, 0xb3, 0x7c, 0x6c, 0xa9, 0xd2, 0xd2, 0xb7, 0xe7, 0xb0, 0x80, - 0x5a, 0xb2, 0xc8, 0x68, 0x85, 0x24, 0xb7, 0x32, 0x95, 0xe4, 0xc6, 0x4d, 0x64, 0x3d, 0x5b, 0xf8, - 0x3b, 0x49, 0x0d, 0xbb, 0x07, 0xaa, 0x1d, 0xc5, 0x24, 0xd6, 0x52, 0x37, 0xa6, 0xb0, 0xfe, 0x00, - 0xae, 0xad, 0x05, 0x81, 0x7b, 0x91, 0x54, 0xff, 0xe4, 0x46, 0xdd, 0xac, 0x44, 0xa8, 0xc8, 0xb8, - 0x50, 0x80, 0xfa, 0x16, 0x34, 0x93, 0x0c, 0xc3, 0x53, 0x1e, 0x9b, 0xa4, 0xf1, 0x5c, 0xa7, 0x10, - 0x62, 0xab, 0x02, 0x31, 0x2c, 0xa6, 0xd2, 0xa7, 0xee, 0xb7, 0x02, 0x35, 0xa9, 0x4e, 0x19, 0x54, - 0x2c, 0xdf, 0x16, 0x1b, 0x55, 0x0d, 0x6a, 0x23, 0x57, 0x8d, 0xa3, 0xe3, 0xc4, 0xe3, 0x1d, 0x47, - 0xc7, 0xfa, 0x7f, 0x95, 0xa0, 0xb5, 0x4e, 0x99, 0xa1, 0xe4, 0x8c, 0xb9, 0xac, 0xa9, 0x52, 0xc8, - 0x9a, 0xe6, 0x33, 0xa4, 0xa5, 0x42, 0x86, 0xb4, 0x70, 0xa0, 0x72, 0xd1, 0x4d, 0x7d, 0x13, 0xea, - 0x13, 0xcf, 0x39, 0x4f, 0xec, 0x84, 0x66, 0xd4, 0x10, 0x1c, 0x46, 0x6c, 0x09, 0x1a, 0x68, 0x4a, - 0x1c, 0x4f, 0x64, 0x25, 0x45, 0x6a, 0x31, 0x8f, 0x9a, 0xca, 0x3d, 0xd6, 0x5e, 0x9e, 0x7b, 0xac, - 0x7f, 0x93, 0xdc, 0xa3, 0xfa, 0x0d, 0x72, 0x8f, 0xda, 0x74, 0xee, 0xb1, 0xe8, 0x88, 0xc3, 0x25, - 0x47, 0xfc, 0x16, 0x80, 0xf8, 0x34, 0xe7, 0x68, 0xe2, 0xba, 0xd2, 0xbb, 0xd1, 0x08, 0xb3, 0x35, - 0x71, 0x5d, 0x7d, 0x07, 0xda, 0xc9, 0x03, 0x48, 0x45, 0xf1, 0x29, 0xcc, 0xcb, 0xda, 0x03, 0x0f, - 0x65, 0x3a, 0x4d, 0xe8, 0x3f, 0x92, 0x52, 0x51, 0x1e, 0x90, 0x3d, 0x46, 0xdb, 0xce, 0x83, 0x91, - 0xfe, 0x4b, 0x05, 0x5a, 0x85, 0x11, 0xec, 0x51, 0x56, 0xc9, 0x50, 0x48, 0xd6, 0xbb, 0x97, 0x56, - 0x79, 0x79, 0x35, 0xa3, 0x34, 0x55, 0xcd, 0xd0, 0xef, 0xa7, 0x35, 0x0a, 0x59, 0x99, 0x98, 0x4b, - 0x2b, 0x13, 0x94, 0xcc, 0x5f, 0x1b, 0x0e, 0x8d, 0x4e, 0x89, 0xd5, 0xa0, 0xb4, 0x3b, 0xe8, 0x94, - 0xf5, 0xdf, 0x94, 0xa0, 0xd5, 0x3f, 0x0f, 0xe8, 0x33, 0xb5, 0xaf, 0x8d, 0x6a, 0x72, 0xdc, 0x57, - 0x2a, 0x70, 0x5f, 0x8e, 0x8f, 0xca, 0xb2, 0x34, 0x2b, 0xf8, 0x08, 0xe3, 0x1c, 0x91, 0x09, 0x95, - 0xfc, 0x25, 0xa0, 0xff, 0x3b, 0xfc, 0x55, 0xd0, 0x4e, 0x30, 0x5d, 0x82, 0xdb, 0x81, 0x76, 0x42, - 0x5c, 0xc9, 0x3e, 0xaf, 0x24, 0xf8, 0xe2, 0xf3, 0x55, 0x37, 0x4d, 0xba, 0x09, 0x40, 0xff, 0xd3, - 0x12, 0x68, 0x82, 0x1b, 0xf1, 0x3e, 0x1f, 0x48, 0x1b, 0xa1, 0x64, 0xd5, 0x9e, 0xb4, 0x73, 0xe5, - 0x09, 0xbf, 0xc8, 0xec, 0xc4, 0xcc, 0x0a, 0xa9, 0x4c, 0xcd, 0x89, 0xec, 0x04, 0xa5, 0xe6, 0x6e, - 0x82, 0x26, 0x5c, 0xbc, 0x89, 0x2c, 0x35, 0x54, 0x0c, 0xe1, 0xf3, 0x1d, 0x38, 0x64, 0xa5, 0x62, - 0x1e, 0x8e, 0xe5, 0x4b, 0x51, 0xbb, 0x18, 0x07, 0xb6, 0x92, 0xc8, 0xa4, 0x40, 0x91, 0xfa, 0x34, - 0x45, 0x4e, 0xa0, 0x2e, 0xcf, 0x86, 0x6e, 0xfc, 0xc1, 0xee, 0x93, 0xdd, 0xbd, 0x1f, 0xee, 0x16, - 0x78, 0x34, 0x75, 0xf4, 0x4b, 0x79, 0x47, 0xbf, 0x8c, 0xf8, 0x8d, 0xbd, 0x83, 0xdd, 0x61, 0xa7, - 0xc2, 0x5a, 0xa0, 0x51, 0x73, 0x64, 0xf4, 0x9f, 0x75, 0xaa, 0x94, 0xd9, 0xda, 0xf8, 0xac, 0xff, - 0x74, 0xad, 0x53, 0x4b, 0x6b, 0x6f, 0x75, 0xfd, 0x4f, 0x14, 0x58, 0x10, 0x04, 0xc9, 0x27, 0x79, - 0xf2, 0x1f, 0x96, 0x57, 0xc4, 0x87, 0xe5, 0xff, 0xbb, 0x79, 0x1d, 0x9c, 0x34, 0x71, 0x92, 0x6a, - 0xb7, 0x48, 0x38, 0xaa, 0x13, 0x47, 0x16, 0xb9, 0xff, 0x4e, 0x81, 0x9e, 0x88, 0x2f, 0x1e, 0x87, - 0x66, 0x70, 0xf2, 0x83, 0x9d, 0x4b, 0x19, 0x86, 0xab, 0xbc, 0xee, 0x3b, 0xd0, 0xa6, 0x4f, 0xef, - 0x7f, 0xe6, 0x8e, 0x64, 0x14, 0x2c, 0x5e, 0xb7, 0x25, 0xb1, 0x62, 0x21, 0xf6, 0x11, 0x34, 0xc5, - 0x27, 0xfa, 0x94, 0x81, 0x2f, 0x54, 0x6a, 0x0b, 0xd1, 0x4d, 0x43, 0x8c, 0x12, 0x75, 0xe5, 0x47, - 0xe9, 0xa4, 0x2c, 0x19, 0x71, 0xb9, 0x18, 0x2b, 0xa7, 0x0c, 0x29, 0x45, 0xf1, 0x00, 0x6e, 0xce, - 0xbc, 0x87, 0x64, 0xfb, 0x5c, 0x22, 0x58, 0x70, 0x9b, 0xfe, 0x1b, 0x05, 0xd4, 0xf5, 0x89, 0x7b, - 0x4a, 0x06, 0xf5, 0x16, 0x00, 0xb7, 0x8f, 0xb9, 0xfc, 0xd6, 0x5d, 0x21, 0x15, 0xa2, 0x21, 0x46, - 0x7c, 0xed, 0xfe, 0x29, 0x80, 0xb8, 0xe3, 0x68, 0x6c, 0x06, 0xf2, 0x89, 0xa8, 0x72, 0x9a, 0x2c, - 0x20, 0xef, 0xf2, 0xd4, 0x0c, 0x64, 0xe5, 0x34, 0x4a, 0xe0, 0xac, 0xa2, 0x5c, 0x7e, 0x49, 0x45, - 0xb9, 0xb7, 0x0b, 0xed, 0xe2, 0x12, 0x33, 0x12, 0x70, 0xef, 0x15, 0xbf, 0xda, 0xb9, 0x4c, 0xc3, - 0x5c, 0x3c, 0xf0, 0x39, 0xcc, 0x4f, 0x25, 0xf3, 0x5f, 0xa6, 0x57, 0x0b, 0x22, 0x53, 0x9a, 0x16, - 0x99, 0x0f, 0x61, 0x61, 0x68, 0x46, 0xa7, 0x32, 0x46, 0xca, 0x1c, 0x81, 0xd8, 0x8c, 0x4e, 0x47, - 0x29, 0x51, 0x6b, 0x08, 0x6e, 0xdb, 0xfa, 0x23, 0x60, 0xf9, 0xd1, 0x92, 0xfe, 0x18, 0xfb, 0xe2, - 0xf0, 0x31, 0x8f, 0xcd, 0xc4, 0x63, 0x41, 0x04, 0x12, 0x6f, 0xf5, 0x6f, 0x15, 0xa8, 0x60, 0x50, - 0xc1, 0xee, 0x83, 0xf6, 0x19, 0x37, 0xc3, 0xf8, 0x90, 0x9b, 0x31, 0x2b, 0x04, 0x10, 0x3d, 0xa2, - 0x5b, 0xf6, 0x25, 0x90, 0x3e, 0xf7, 0x50, 0x61, 0x2b, 0xe2, 0x3b, 0xe5, 0xe4, 0xfb, 0xeb, 0x56, - 0x12, 0x9c, 0x50, 0xf0, 0xd2, 0x2b, 0xcc, 0xd7, 0xe7, 0x96, 0x69, 0xfc, 0xe7, 0xbe, 0xe3, 0x6d, - 0x88, 0xaf, 0x63, 0xd9, 0x74, 0x30, 0x33, 0x3d, 0x83, 0xdd, 0x87, 0xda, 0x76, 0x84, 0x51, 0xd3, - 0xe5, 0xa1, 0x44, 0xfc, 0x7c, 0x40, 0xa5, 0xcf, 0xad, 0xfe, 0x45, 0x15, 0x2a, 0x3f, 0xe1, 0xa1, - 0xcf, 0x3e, 0x84, 0xba, 0xfc, 0x6e, 0x8a, 0xe5, 0xbe, 0x8f, 0xea, 0x51, 0x02, 0x67, 0xea, 0x83, - 0x2a, 0xda, 0xa5, 0x23, 0xde, 0x2f, 0x2b, 0x61, 0xb1, 0xec, 0xb3, 0xae, 0x4b, 0x87, 0xfa, 0x04, - 0x3a, 0x83, 0x38, 0xe4, 0xe6, 0x38, 0x37, 0xbc, 0x48, 0xaa, 0x59, 0xf5, 0x30, 0xa2, 0xd7, 0x3d, - 0xa8, 0x89, 0xd0, 0x74, 0x6a, 0xc2, 0x74, 0xb1, 0x8b, 0x06, 0xbf, 0x0f, 0x8d, 0xc1, 0x89, 0x3f, - 0x71, 0xed, 0x01, 0x0f, 0xcf, 0x38, 0xcb, 0x45, 0x57, 0xbd, 0x5c, 0x5b, 0x9f, 0x63, 0x8f, 0xa0, - 0x86, 0x2f, 0x12, 0x8e, 0xd9, 0x42, 0x2e, 0x02, 0x13, 0x6c, 0xd2, 0x63, 0x79, 0x54, 0x42, 0x29, - 0xf6, 0x3e, 0x68, 0x22, 0x14, 0xc0, 0x40, 0xa0, 0x2e, 0xa3, 0x0b, 0x71, 0x8c, 0x5c, 0x88, 0xa0, - 0xcf, 0xb1, 0x65, 0x80, 0x5c, 0x4c, 0xfb, 0xb2, 0x91, 0x1f, 0x41, 0x6b, 0x83, 0x34, 0xe1, 0x5e, - 0xb8, 0x76, 0xe8, 0x87, 0x31, 0x9b, 0xfe, 0x96, 0xb3, 0x37, 0x8d, 0xd0, 0xe7, 0x30, 0x3a, 0x1c, - 0x86, 0x17, 0x62, 0xfc, 0x82, 0x4c, 0x05, 0x64, 0xfb, 0xcd, 0xa0, 0x0b, 0xfb, 0x38, 0x95, 0xab, - 0x34, 0x02, 0x98, 0x55, 0x39, 0x13, 0x24, 0x12, 0x32, 0x40, 0x24, 0x82, 0x2c, 0x3c, 0x61, 0x6f, - 0x88, 0x2a, 0xde, 0x54, 0xb8, 0x72, 0x79, 0x4a, 0x16, 0x8a, 0x88, 0x29, 0x97, 0x42, 0x93, 0xa9, - 0x29, 0xdf, 0x86, 0x66, 0x3e, 0xac, 0x60, 0x54, 0x8e, 0x9a, 0x11, 0x68, 0x14, 0xa7, 0xad, 0xfe, - 0x7b, 0x15, 0x6a, 0x3f, 0xf4, 0xc3, 0x53, 0x1e, 0xb2, 0xbb, 0x50, 0xa3, 0x7a, 0xac, 0x94, 0xa5, - 0xb4, 0x36, 0x3b, 0x8b, 0x76, 0xef, 0x82, 0x46, 0x9c, 0x81, 0xc2, 0x2e, 0xf8, 0x95, 0xfe, 0x7b, - 0x24, 0x16, 0x17, 0x19, 0x52, 0x62, 0xee, 0xb6, 0xe0, 0xd6, 0xf4, 0xfb, 0x88, 0x42, 0xbd, 0xb4, - 0x47, 0x4f, 0xfa, 0xe4, 0xd9, 0x00, 0xe5, 0xf3, 0xa1, 0x82, 0x3e, 0xc5, 0x40, 0x3c, 0x1e, 0x0e, - 0xca, 0xfe, 0x5b, 0x21, 0xc4, 0x3f, 0xfb, 0x33, 0x83, 0x3e, 0xc7, 0x1e, 0x40, 0x4d, 0x9a, 0x98, - 0x85, 0x4c, 0x11, 0x26, 0x37, 0xec, 0xe4, 0x51, 0x72, 0xc2, 0x23, 0xa8, 0x09, 0x73, 0x2c, 0x26, - 0x14, 0xe2, 0x1a, 0xc1, 0xa7, 0x45, 0x4f, 0x5b, 0x9f, 0x63, 0xf7, 0xa0, 0x2e, 0xab, 0xad, 0x6c, - 0x46, 0xe9, 0xf5, 0xd2, 0x8b, 0xd5, 0x84, 0xaf, 0x25, 0xd6, 0x2f, 0x38, 0xb5, 0x62, 0xfd, 0xa2, - 0x2b, 0x26, 0x44, 0xdf, 0xe0, 0x16, 0x77, 0x72, 0x89, 0x39, 0x96, 0x50, 0x64, 0x86, 0xfe, 0xfa, - 0x04, 0x5a, 0x85, 0x24, 0x1e, 0xeb, 0x26, 0x6c, 0x31, 0x9d, 0xd7, 0xbb, 0xa4, 0x35, 0xbe, 0x07, - 0x9a, 0x4c, 0x3b, 0x1c, 0x4a, 0xc6, 0x98, 0x91, 0xe4, 0xe8, 0x5d, 0xce, 0x3b, 0x90, 0x2a, 0xf8, - 0x11, 0x5c, 0x9b, 0x61, 0x5b, 0x19, 0x7d, 0x9d, 0x7b, 0xb5, 0xf3, 0xd0, 0x5b, 0xbc, 0xb2, 0x3f, - 0x25, 0xc0, 0x37, 0x13, 0xa7, 0xef, 0x03, 0x64, 0x26, 0x46, 0xc8, 0xc6, 0x25, 0x03, 0xd5, 0xbb, - 0x31, 0x8d, 0x4e, 0x36, 0x5d, 0xef, 0xfe, 0xea, 0xcb, 0xdb, 0xca, 0xaf, 0xbf, 0xbc, 0xad, 0xfc, - 0xcb, 0x97, 0xb7, 0x95, 0x5f, 0x7e, 0x75, 0x7b, 0xee, 0xd7, 0x5f, 0xdd, 0x9e, 0xfb, 0x87, 0xaf, - 0x6e, 0xcf, 0x1d, 0xd6, 0xe8, 0x4f, 0x80, 0x1f, 0xfd, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2f, - 0xd4, 0x6f, 0x28, 0x7a, 0x38, 0x00, 0x00, + // 5512 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x7b, 0xcd, 0x6f, 0x1c, 0x57, + 0x72, 0x38, 0xe7, 0x7b, 0xba, 0x86, 0x33, 0x1a, 0x3e, 0xc9, 0xf2, 0xec, 0xc8, 0x12, 0xb5, 0x6d, + 0xcb, 0xa6, 0x25, 0x8b, 0x92, 0x68, 0xef, 0xfe, 0xd6, 0x5e, 0x2c, 0xf0, 0x23, 0xc5, 0xa1, 0x4c, + 0x8b, 0x22, 0xb5, 0x3d, 0x23, 0xed, 0x07, 0x90, 0x0c, 0x9a, 0xdd, 0x8f, 0x64, 0x2f, 0x7b, 0xba, + 0x7b, 0xbb, 0x7b, 0xb8, 0xa4, 0x6f, 0xb9, 0x64, 0x0f, 0xc9, 0x61, 0x81, 0x5c, 0x02, 0x04, 0x08, + 0x90, 0x5c, 0x93, 0x53, 0x10, 0x20, 0x41, 0x80, 0xdc, 0x82, 0x60, 0x91, 0xd3, 0x1e, 0x83, 0x6c, + 0x22, 0x04, 0xde, 0x20, 0x07, 0x1d, 0x02, 0xe4, 0x2f, 0x48, 0x50, 0x55, 0xaf, 0xbf, 0x86, 0x43, + 0x59, 0x76, 0x90, 0x4b, 0x4e, 0xf3, 0xaa, 0xde, 0x77, 0x55, 0xbd, 0xfa, 0xec, 0x81, 0x66, 0xb0, + 0xbf, 0x1a, 0x84, 0x7e, 0xec, 0x8b, 0x72, 0xb0, 0xdf, 0xd7, 0xcc, 0xc0, 0x61, 0xb0, 0x7f, 0xfb, + 0xd0, 0x89, 0x8f, 0xa6, 0xfb, 0xab, 0x96, 0x3f, 0xb9, 0x67, 0x1f, 0x86, 0x66, 0x70, 0x74, 0xd7, + 0xf1, 0xef, 0xed, 0x9b, 0xf6, 0xa1, 0x0c, 0xef, 0x9d, 0x7c, 0x74, 0x2f, 0xd8, 0xbf, 0x97, 0x4c, + 0xed, 0xdf, 0xcd, 0x8d, 0x3d, 0xf4, 0x0f, 0xfd, 0x7b, 0x84, 0xde, 0x9f, 0x1e, 0x10, 0x44, 0x00, + 0xb5, 0x78, 0xb8, 0xde, 0x87, 0xea, 0x8e, 0x13, 0xc5, 0x42, 0x40, 0x75, 0xea, 0xd8, 0x51, 0xaf, + 0x74, 0xb3, 0xb2, 0x52, 0x37, 0xa8, 0xad, 0x3f, 0x01, 0x6d, 0x64, 0x46, 0xc7, 0xcf, 0x4d, 0x77, + 0x2a, 0x45, 0x17, 0x2a, 0x27, 0xa6, 0xdb, 0x2b, 0xdd, 0x2c, 0xad, 0x2c, 0x1a, 0xd8, 0x14, 0xab, + 0xd0, 0x3c, 0x31, 0xdd, 0x71, 0x7c, 0x16, 0xc8, 0x5e, 0xf9, 0x66, 0x69, 0xa5, 0xb3, 0x76, 0x79, + 0x35, 0xd8, 0x5f, 0x7d, 0xea, 0x47, 0xb1, 0xe3, 0x1d, 0xae, 0x3e, 0x37, 0xdd, 0xd1, 0x59, 0x20, + 0x8d, 0xc6, 0x09, 0x37, 0xf4, 0x3d, 0x68, 0x0d, 0x43, 0x6b, 0x6b, 0xea, 0x59, 0xb1, 0xe3, 0x7b, + 0xb8, 0xa3, 0x67, 0x4e, 0x24, 0xad, 0xa8, 0x19, 0xd4, 0x46, 0x9c, 0x19, 0x1e, 0x46, 0xbd, 0xca, + 0xcd, 0x0a, 0xe2, 0xb0, 0x2d, 0x7a, 0xd0, 0x70, 0xa2, 0x87, 0xfe, 0xd4, 0x8b, 0x7b, 0xd5, 0x9b, + 0xa5, 0x95, 0xa6, 0x91, 0x80, 0xfa, 0x5f, 0x55, 0xa0, 0xf6, 0xfd, 0xa9, 0x0c, 0xcf, 0x68, 0x5e, + 0x1c, 0x87, 0xc9, 0x5a, 0xd8, 0x16, 0x57, 0xa0, 0xe6, 0x9a, 0xde, 0x61, 0xd4, 0x2b, 0xd3, 0x62, + 0x0c, 0x88, 0x6b, 0xa0, 0x99, 0x07, 0xb1, 0x0c, 0xc7, 0x53, 0xc7, 0xee, 0x55, 0x6e, 0x96, 0x56, + 0xea, 0x46, 0x93, 0x10, 0xcf, 0x1c, 0x5b, 0x7c, 0x03, 0x9a, 0xb6, 0x3f, 0xb6, 0xf2, 0x7b, 0xd9, + 0x3e, 0xed, 0x25, 0xde, 0x86, 0xe6, 0xd4, 0xb1, 0xc7, 0xae, 0x13, 0xc5, 0xbd, 0xda, 0xcd, 0xd2, + 0x4a, 0x6b, 0xad, 0x89, 0x97, 0x45, 0xda, 0x19, 0x8d, 0xa9, 0x63, 0x13, 0x11, 0x6f, 0x43, 0x33, + 0x0a, 0xad, 0xf1, 0xc1, 0xd4, 0xb3, 0x7a, 0x75, 0x1a, 0x74, 0x09, 0x07, 0xe5, 0x6e, 0x6d, 0x34, + 0x22, 0x06, 0xf0, 0x5a, 0xa1, 0x3c, 0x91, 0x61, 0x24, 0x7b, 0x0d, 0xde, 0x4a, 0x81, 0xe2, 0x3e, + 0xb4, 0x0e, 0x4c, 0x4b, 0xc6, 0xe3, 0xc0, 0x0c, 0xcd, 0x49, 0xaf, 0x99, 0x2d, 0xb4, 0x85, 0xe8, + 0xa7, 0x88, 0x8d, 0x0c, 0x38, 0x48, 0x01, 0xf1, 0x21, 0xb4, 0x09, 0x8a, 0xc6, 0x07, 0x8e, 0x1b, + 0xcb, 0xb0, 0xa7, 0xd1, 0x9c, 0x0e, 0xcd, 0x21, 0xcc, 0x28, 0x94, 0xd2, 0x58, 0xe4, 0x41, 0x8c, + 0x11, 0xd7, 0x01, 0xe4, 0x69, 0x60, 0x7a, 0xf6, 0xd8, 0x74, 0xdd, 0x1e, 0xd0, 0x19, 0x34, 0xc6, + 0xac, 0xbb, 0xae, 0x78, 0x13, 0xcf, 0x67, 0xda, 0xe3, 0x38, 0xea, 0xb5, 0x6f, 0x96, 0x56, 0xaa, + 0x46, 0x1d, 0xc1, 0x51, 0x84, 0x74, 0xb5, 0x4c, 0xeb, 0x48, 0xf6, 0x3a, 0x37, 0x4b, 0x2b, 0x35, + 0x83, 0x01, 0xc4, 0x1e, 0x38, 0x61, 0x14, 0xf7, 0x2e, 0x31, 0x96, 0x00, 0x71, 0x15, 0xea, 0xfe, + 0xc1, 0x41, 0x24, 0xe3, 0x5e, 0x97, 0xd0, 0x0a, 0xd2, 0xd7, 0x40, 0x23, 0xa9, 0x22, 0xaa, 0xdd, + 0x82, 0xfa, 0x09, 0x02, 0x2c, 0x7c, 0xad, 0xb5, 0x36, 0x1e, 0x3b, 0x15, 0x3c, 0x43, 0x75, 0xea, + 0x37, 0xa0, 0xb9, 0x63, 0x7a, 0x87, 0x89, 0xb4, 0x22, 0x3b, 0x69, 0x82, 0x66, 0x50, 0x5b, 0xff, + 0xc3, 0x32, 0xd4, 0x0d, 0x19, 0x4d, 0xdd, 0x58, 0xbc, 0x07, 0x80, 0xcc, 0x9a, 0x98, 0x71, 0xe8, + 0x9c, 0xaa, 0x55, 0x33, 0x76, 0x69, 0x53, 0xc7, 0x7e, 0x42, 0x5d, 0xe2, 0x3e, 0x2c, 0xd2, 0xea, + 0xc9, 0xd0, 0x72, 0x76, 0x80, 0xf4, 0x7c, 0x46, 0x8b, 0x86, 0xa8, 0x19, 0x57, 0xa1, 0x4e, 0xf2, + 0xc1, 0x32, 0xda, 0x36, 0x14, 0x24, 0x6e, 0x41, 0xc7, 0xf1, 0x62, 0xe4, 0x9f, 0x15, 0x8f, 0x6d, + 0x19, 0x25, 0x02, 0xd4, 0x4e, 0xb1, 0x9b, 0x32, 0x8a, 0xc5, 0x03, 0x60, 0x26, 0x24, 0x1b, 0xd6, + 0x68, 0xc3, 0x4e, 0xca, 0xdc, 0x88, 0x77, 0xa4, 0x31, 0x6a, 0xc7, 0xbb, 0xd0, 0xc2, 0xfb, 0x25, + 0x33, 0xea, 0x34, 0x63, 0x91, 0x6e, 0xa3, 0xc8, 0x61, 0x00, 0x0e, 0x50, 0xc3, 0x91, 0x34, 0x28, + 0xa4, 0x2c, 0x54, 0xd4, 0xd6, 0x07, 0x50, 0xdb, 0x0b, 0x6d, 0x19, 0xce, 0x7d, 0x27, 0x02, 0xaa, + 0xb6, 0x8c, 0x2c, 0x7a, 0xc2, 0x4d, 0x83, 0xda, 0xd9, 0xdb, 0xa9, 0xe4, 0xde, 0x8e, 0xfe, 0xc7, + 0x25, 0x68, 0x0d, 0xfd, 0x30, 0x7e, 0x22, 0xa3, 0xc8, 0x3c, 0x94, 0x62, 0x19, 0x6a, 0x3e, 0x2e, + 0xab, 0x28, 0xac, 0xe1, 0x99, 0x68, 0x1f, 0x83, 0xf1, 0x33, 0x7c, 0x28, 0x5f, 0xcc, 0x07, 0x94, + 0x29, 0x7a, 0x75, 0x15, 0x25, 0x53, 0xf4, 0xe6, 0x32, 0xe9, 0xa9, 0xe6, 0xa5, 0xe7, 0x42, 0xd1, + 0xd4, 0xbf, 0x05, 0x80, 0xe7, 0xfb, 0x8a, 0x52, 0xa0, 0xff, 0xbc, 0x04, 0x2d, 0xc3, 0x3c, 0x88, + 0x1f, 0xfa, 0x5e, 0x2c, 0x4f, 0x63, 0xd1, 0x81, 0xb2, 0x63, 0x13, 0x8d, 0xea, 0x46, 0xd9, 0xb1, + 0xf1, 0x74, 0x87, 0xa1, 0x3f, 0x0d, 0x88, 0x44, 0x6d, 0x83, 0x01, 0xa2, 0xa5, 0x6d, 0x87, 0x74, + 0x64, 0xa4, 0xa5, 0x6d, 0x87, 0x62, 0x19, 0x5a, 0x91, 0x67, 0x06, 0xd1, 0x91, 0x1f, 0xe3, 0xe9, + 0xaa, 0x74, 0x3a, 0x48, 0x50, 0xa3, 0x08, 0x1f, 0x9d, 0x13, 0x8d, 0x5d, 0x69, 0x86, 0x9e, 0x0c, + 0x49, 0x91, 0x34, 0x0d, 0xcd, 0x89, 0x76, 0x18, 0xa1, 0xff, 0xbc, 0x02, 0xf5, 0x27, 0x72, 0xb2, + 0x2f, 0xc3, 0x73, 0x87, 0xb8, 0x0f, 0x4d, 0xda, 0x77, 0xec, 0xd8, 0x7c, 0x8e, 0x8d, 0x37, 0x5e, + 0xbe, 0x58, 0x5e, 0x22, 0xdc, 0xb6, 0xfd, 0x81, 0x3f, 0x71, 0x62, 0x39, 0x09, 0xe2, 0x33, 0xa3, + 0xa1, 0x50, 0x73, 0x0f, 0x78, 0x15, 0xea, 0xae, 0x34, 0x91, 0x67, 0x2c, 0x9e, 0x0a, 0x12, 0x77, + 0xa1, 0x61, 0x4e, 0xc6, 0xb6, 0x34, 0x6d, 0x3e, 0xd4, 0xc6, 0x95, 0x97, 0x2f, 0x96, 0xbb, 0xe6, + 0x64, 0x53, 0x9a, 0xf9, 0xb5, 0xeb, 0x8c, 0x11, 0x1f, 0xa3, 0x4c, 0x46, 0xf1, 0x78, 0x1a, 0xd8, + 0x66, 0x2c, 0x49, 0xd7, 0x55, 0x37, 0x7a, 0x2f, 0x5f, 0x2c, 0x5f, 0x41, 0xf4, 0x33, 0xc2, 0xe6, + 0xa6, 0x41, 0x86, 0x45, 0xbd, 0x97, 0x5c, 0x5f, 0xe9, 0x3d, 0x05, 0x8a, 0x6d, 0x58, 0xb2, 0xdc, + 0x69, 0x84, 0xca, 0xd9, 0xf1, 0x0e, 0xfc, 0xb1, 0xef, 0xb9, 0x67, 0xc4, 0xe0, 0xe6, 0xc6, 0xf5, + 0x97, 0x2f, 0x96, 0xbf, 0xa1, 0x3a, 0xb7, 0xbd, 0x03, 0x7f, 0xcf, 0x73, 0xcf, 0x72, 0xeb, 0x5f, + 0x9a, 0xe9, 0x12, 0xff, 0x1f, 0x3a, 0x07, 0x7e, 0x68, 0xc9, 0x71, 0x4a, 0xb2, 0x0e, 0xad, 0xd3, + 0x7f, 0xf9, 0x62, 0xf9, 0x2a, 0xf5, 0x3c, 0x3a, 0x47, 0xb7, 0xc5, 0x3c, 0x5e, 0xff, 0x97, 0x32, + 0xd4, 0xa8, 0x2d, 0xee, 0x43, 0x63, 0x42, 0x2c, 0x49, 0xf4, 0xd3, 0x55, 0x94, 0x21, 0xea, 0x5b, + 0x65, 0x5e, 0x45, 0x03, 0x2f, 0x0e, 0xcf, 0x8c, 0x64, 0x18, 0xce, 0x88, 0xcd, 0x7d, 0x57, 0xc6, + 0x91, 0x92, 0xf9, 0xdc, 0x8c, 0x11, 0x77, 0xa8, 0x19, 0x6a, 0xd8, 0xac, 0xdc, 0x54, 0xce, 0xc9, + 0x4d, 0x1f, 0x9a, 0xd6, 0x91, 0xb4, 0x8e, 0xa3, 0xe9, 0x44, 0x49, 0x55, 0x0a, 0x8b, 0xb7, 0xa1, + 0x4d, 0xed, 0xc0, 0x77, 0x3c, 0x9a, 0x5e, 0xa3, 0x01, 0x8b, 0x19, 0x72, 0x14, 0xf5, 0xb7, 0x60, + 0x31, 0x7f, 0x58, 0x34, 0xe7, 0xc7, 0xf2, 0x8c, 0xe4, 0xab, 0x6a, 0x60, 0x53, 0xdc, 0x84, 0x1a, + 0x29, 0x3a, 0x92, 0xae, 0xd6, 0x1a, 0xe0, 0x99, 0x79, 0x8a, 0xc1, 0x1d, 0x9f, 0x94, 0xbf, 0x53, + 0xc2, 0x75, 0xf2, 0x57, 0xc8, 0xaf, 0xa3, 0x5d, 0xbc, 0x0e, 0x4f, 0xc9, 0xad, 0xa3, 0xfb, 0xd0, + 0xd8, 0x71, 0x2c, 0xe9, 0x45, 0x64, 0xf4, 0xa7, 0x91, 0x4c, 0x95, 0x12, 0xb6, 0xf1, 0xbe, 0x13, + 0xf3, 0x74, 0xd7, 0xb7, 0x65, 0x44, 0xeb, 0x54, 0x8d, 0x14, 0xc6, 0x3e, 0x79, 0x1a, 0x38, 0xe1, + 0xd9, 0x88, 0x29, 0x55, 0x31, 0x52, 0x18, 0xa5, 0x4b, 0x7a, 0xb8, 0x99, 0x9d, 0x18, 0x70, 0x05, + 0xea, 0x7f, 0x5e, 0x85, 0xc5, 0x1f, 0xcb, 0xd0, 0x7f, 0x1a, 0xfa, 0x81, 0x1f, 0x99, 0xae, 0x58, + 0x2f, 0xd2, 0x9c, 0x79, 0x7b, 0x13, 0x4f, 0x9b, 0x1f, 0xb6, 0x3a, 0x4c, 0x99, 0xc0, 0x3c, 0xcb, + 0x73, 0x45, 0x87, 0x3a, 0xf3, 0x7c, 0x0e, 0xcd, 0x54, 0x0f, 0x8e, 0x61, 0x2e, 0xd3, 0x59, 0x8b, + 0xf4, 0x50, 0x3d, 0xf8, 0x2a, 0x27, 0xe6, 0xe9, 0xb3, 0xed, 0x4d, 0xc5, 0x5b, 0x05, 0x29, 0x2a, + 0x8c, 0x4e, 0xbd, 0x51, 0xc2, 0xd4, 0x14, 0xc6, 0x9b, 0x22, 0x45, 0xa2, 0xed, 0xcd, 0xde, 0x22, + 0x75, 0x25, 0xa0, 0x78, 0x0b, 0xb4, 0x89, 0x79, 0x8a, 0x0a, 0x6d, 0xdb, 0xe6, 0xa7, 0x69, 0x64, + 0x08, 0xf1, 0x4d, 0xa8, 0xc4, 0xa7, 0x1e, 0xbd, 0x3d, 0xf4, 0x2a, 0xd0, 0xc9, 0x1c, 0x9d, 0x7a, + 0x4a, 0xf5, 0x19, 0xd8, 0x87, 0x3c, 0xb5, 0x1c, 0x9b, 0x9c, 0x08, 0xcd, 0xc0, 0xa6, 0xb8, 0x05, + 0x0d, 0x97, 0xb9, 0x45, 0x8e, 0x42, 0x6b, 0xad, 0xc5, 0x7a, 0x94, 0x50, 0x46, 0xd2, 0x27, 0x3e, + 0x80, 0x66, 0x42, 0x9d, 0x5e, 0x8b, 0xc6, 0x75, 0x13, 0x7a, 0x26, 0x64, 0x34, 0xd2, 0x11, 0xe2, + 0x3e, 0x68, 0xb6, 0x74, 0x65, 0x2c, 0xc7, 0x1e, 0x2b, 0xf2, 0x16, 0x3b, 0x90, 0x9b, 0x84, 0xdc, + 0x8d, 0x0c, 0xf9, 0xd3, 0xa9, 0x8c, 0x62, 0xa3, 0x69, 0x2b, 0x84, 0x78, 0x27, 0x7b, 0x58, 0x1d, + 0x62, 0x57, 0x9e, 0x98, 0x49, 0x57, 0xff, 0x7b, 0x70, 0x69, 0x86, 0x69, 0x79, 0x29, 0x6d, 0xb3, + 0x94, 0x5e, 0xc9, 0x4b, 0x69, 0x35, 0x27, 0x99, 0x9f, 0x55, 0x9b, 0xcd, 0xae, 0xa6, 0xff, 0x67, + 0x05, 0x2e, 0xa9, 0x07, 0x73, 0xe4, 0x04, 0xc3, 0x58, 0xa9, 0x2e, 0x32, 0x4c, 0x4a, 0x56, 0xab, + 0x46, 0x02, 0x8a, 0xff, 0x07, 0x75, 0xd2, 0x34, 0xc9, 0x83, 0x5f, 0xce, 0x04, 0x21, 0x9d, 0xce, + 0x0a, 0x40, 0x49, 0x91, 0x1a, 0x2e, 0x3e, 0x82, 0xda, 0xe7, 0x32, 0xf4, 0xd9, 0xd0, 0xb6, 0xd6, + 0x6e, 0xcc, 0x9b, 0x87, 0xe4, 0x53, 0xd3, 0x78, 0xf0, 0xff, 0x54, 0x5e, 0xe0, 0xab, 0xc8, 0xcb, + 0x3b, 0x68, 0x6c, 0x27, 0xfe, 0x89, 0xb4, 0x7b, 0x8d, 0x8c, 0xe6, 0x4a, 0xc8, 0x93, 0xae, 0x44, + 0x64, 0x9a, 0x73, 0x45, 0x46, 0xbb, 0x58, 0x64, 0xfa, 0x9b, 0xd0, 0xca, 0xd1, 0x65, 0x0e, 0xa3, + 0x96, 0x8b, 0xea, 0x44, 0x4b, 0x55, 0x69, 0x5e, 0x2b, 0x6d, 0x02, 0x64, 0x54, 0xfa, 0xba, 0xba, + 0x4d, 0xff, 0x9d, 0x12, 0x5c, 0x7a, 0xe8, 0x7b, 0x9e, 0x24, 0x57, 0x9d, 0x79, 0x9e, 0x3d, 0xf1, + 0xd2, 0x85, 0x4f, 0xfc, 0x7d, 0xa8, 0x45, 0x38, 0x58, 0xad, 0x7e, 0x79, 0x0e, 0x13, 0x0d, 0x1e, + 0x81, 0x8a, 0x7e, 0x62, 0x9e, 0x8e, 0x03, 0xe9, 0xd9, 0x8e, 0x77, 0x98, 0x28, 0xfa, 0x89, 0x79, + 0xfa, 0x94, 0x31, 0xfa, 0x5f, 0x97, 0x01, 0x3e, 0x95, 0xa6, 0x1b, 0x1f, 0xa1, 0x31, 0x43, 0x8e, + 0x3a, 0x5e, 0x14, 0x9b, 0x9e, 0x95, 0x04, 0x4a, 0x29, 0x8c, 0x1c, 0x45, 0x9b, 0x2e, 0x23, 0x56, + 0x91, 0x9a, 0x91, 0x80, 0x28, 0x1f, 0xb8, 0xdd, 0x34, 0x52, 0xb6, 0x5f, 0x41, 0x99, 0x23, 0x53, + 0x25, 0xb4, 0x72, 0x64, 0x7a, 0xd0, 0xc0, 0xc0, 0xc3, 0xf1, 0x3d, 0x12, 0x1a, 0xcd, 0x48, 0x40, + 0x5c, 0x67, 0x1a, 0xc4, 0xce, 0x84, 0x2d, 0x7c, 0xc5, 0x50, 0x10, 0x9e, 0x0a, 0x2d, 0xfa, 0xc0, + 0x3a, 0xf2, 0x49, 0x91, 0x54, 0x8c, 0x14, 0xc6, 0xd5, 0x7c, 0xef, 0xd0, 0xc7, 0xdb, 0x35, 0xc9, + 0x79, 0x4c, 0x40, 0xbe, 0x8b, 0x2d, 0x4f, 0xb1, 0x4b, 0xa3, 0xae, 0x14, 0x46, 0xba, 0x48, 0x39, + 0x3e, 0x90, 0x66, 0x3c, 0x0d, 0x65, 0xd4, 0x03, 0xea, 0x06, 0x29, 0xb7, 0x14, 0x46, 0x7c, 0x13, + 0x16, 0x91, 0x70, 0x66, 0x14, 0x39, 0x87, 0x9e, 0xb4, 0x49, 0xbd, 0x54, 0x0d, 0x24, 0xe6, 0xba, + 0x42, 0xe9, 0x7f, 0x5b, 0x86, 0x3a, 0xeb, 0x82, 0x82, 0xb3, 0x54, 0x7a, 0x2d, 0x67, 0xe9, 0x2d, + 0xd0, 0x82, 0x50, 0xda, 0x8e, 0x95, 0xf0, 0x51, 0x33, 0x32, 0x04, 0x45, 0x37, 0xe8, 0x1d, 0x10, + 0x3d, 0x9b, 0x06, 0x03, 0x42, 0x87, 0xb6, 0xef, 0x8d, 0x6d, 0x27, 0x3a, 0x1e, 0xef, 0x9f, 0xc5, + 0x32, 0x52, 0xb4, 0x68, 0xf9, 0xde, 0xa6, 0x13, 0x1d, 0x6f, 0x20, 0x0a, 0x49, 0xc8, 0x6f, 0x84, + 0xde, 0x46, 0xd3, 0x50, 0x90, 0xf8, 0x10, 0x34, 0xf2, 0x61, 0xc9, 0xc9, 0xd1, 0xc8, 0x39, 0xb9, + 0xfa, 0xf2, 0xc5, 0xb2, 0x40, 0xe4, 0x8c, 0x77, 0xd3, 0x4c, 0x70, 0xe8, 0xa5, 0xe1, 0x64, 0x34, + 0x57, 0xf4, 0x86, 0xd9, 0x4b, 0x43, 0xd4, 0x28, 0xca, 0x7b, 0x69, 0x8c, 0x11, 0x77, 0x41, 0x4c, + 0x3d, 0xcb, 0x9f, 0x04, 0x28, 0x14, 0xd2, 0x56, 0x87, 0x6c, 0xd1, 0x21, 0x97, 0xf2, 0x3d, 0x74, + 0x54, 0xfd, 0x9f, 0xcb, 0xb0, 0xb8, 0xe9, 0x84, 0xd2, 0x8a, 0xa5, 0x3d, 0xb0, 0x0f, 0x25, 0x9e, + 0x5d, 0x7a, 0xb1, 0x13, 0x9f, 0x29, 0x37, 0x54, 0x41, 0x69, 0x14, 0x51, 0x2e, 0x46, 0xdb, 0xfc, + 0xc2, 0x2a, 0x94, 0x20, 0x60, 0x40, 0xac, 0x01, 0x70, 0x7c, 0x45, 0x49, 0x82, 0xea, 0xc5, 0x49, + 0x02, 0x8d, 0x86, 0x61, 0x13, 0x83, 0x70, 0x9e, 0xe3, 0xb0, 0x2f, 0x5a, 0xa7, 0x0c, 0xc2, 0x54, + 0xb2, 0x47, 0x4b, 0x61, 0x5f, 0x83, 0x37, 0xc6, 0xb6, 0x78, 0x1b, 0xca, 0x7e, 0x40, 0xc4, 0x55, + 0x4b, 0xe7, 0xaf, 0xb0, 0xba, 0x17, 0x18, 0x65, 0x3f, 0xc0, 0x57, 0xcc, 0xb1, 0x2f, 0x09, 0x1e, + 0xbe, 0x62, 0xb4, 0x7b, 0x14, 0x71, 0x19, 0xaa, 0x47, 0xe8, 0xb0, 0x68, 0xba, 0xae, 0xff, 0x33, + 0x69, 0x3f, 0x0d, 0xa5, 0x9d, 0xc8, 0x60, 0x01, 0x87, 0x52, 0xe2, 0x99, 0x13, 0x19, 0x05, 0xa6, + 0x25, 0x95, 0x08, 0x66, 0x08, 0xfd, 0x2a, 0x94, 0xf7, 0x02, 0xd1, 0x80, 0xca, 0x70, 0x30, 0xea, + 0x2e, 0x60, 0x63, 0x73, 0xb0, 0xd3, 0x45, 0x8b, 0x52, 0xef, 0x36, 0xf4, 0x2f, 0xca, 0xa0, 0x3d, + 0x99, 0xc6, 0x26, 0xea, 0x96, 0x08, 0x6f, 0x59, 0x94, 0xd0, 0x4c, 0x14, 0xbf, 0x01, 0xcd, 0x28, + 0x36, 0x43, 0xf2, 0x4a, 0xd8, 0x3a, 0x35, 0x08, 0x1e, 0x45, 0xe2, 0x5d, 0xa8, 0x49, 0xfb, 0x50, + 0x26, 0xe6, 0xa2, 0x3b, 0x7b, 0x5f, 0x83, 0xbb, 0xc5, 0x0a, 0xd4, 0x23, 0xeb, 0x48, 0x4e, 0xcc, + 0x5e, 0x35, 0x1b, 0x38, 0x24, 0x0c, 0xbb, 0xe1, 0x86, 0xea, 0x17, 0xef, 0x40, 0x0d, 0x79, 0x13, + 0xa9, 0xb8, 0x92, 0x22, 0x51, 0x64, 0x83, 0x1a, 0xc6, 0x9d, 0x28, 0x78, 0x76, 0xe8, 0x07, 0x63, + 0x3f, 0x20, 0xda, 0x77, 0xd6, 0xae, 0x90, 0x8e, 0x4b, 0x6e, 0xb3, 0xba, 0x19, 0xfa, 0xc1, 0x5e, + 0x60, 0xd4, 0x6d, 0xfa, 0xc5, 0x28, 0x87, 0x86, 0xb3, 0x44, 0xb0, 0x51, 0xd0, 0x10, 0xc3, 0xa9, + 0xa4, 0x15, 0x68, 0x4e, 0x64, 0x6c, 0xda, 0x66, 0x6c, 0x2a, 0xdb, 0xb0, 0xc8, 0x2a, 0x93, 0x71, + 0x46, 0xda, 0xab, 0xdf, 0x83, 0x3a, 0x2f, 0x2d, 0x9a, 0x50, 0xdd, 0xdd, 0xdb, 0x1d, 0x30, 0x59, + 0xd7, 0x77, 0x76, 0xba, 0x25, 0x44, 0x6d, 0xae, 0x8f, 0xd6, 0xbb, 0x65, 0x6c, 0x8d, 0x7e, 0xf4, + 0x74, 0xd0, 0xad, 0xe8, 0xff, 0x50, 0x82, 0x66, 0xb2, 0x8e, 0xf8, 0x04, 0x00, 0x9f, 0xf0, 0xf8, + 0xc8, 0xf1, 0x52, 0x07, 0xef, 0x5a, 0x7e, 0xa7, 0x55, 0xe4, 0xea, 0xa7, 0xd8, 0xcb, 0xe6, 0x95, + 0x5e, 0x3c, 0xc1, 0xfd, 0x21, 0x74, 0x8a, 0x9d, 0x73, 0x3c, 0xdd, 0x3b, 0x79, 0xab, 0xd2, 0x59, + 0x7b, 0xa3, 0xb0, 0x34, 0xce, 0x24, 0xd1, 0xce, 0x19, 0x98, 0xbb, 0xd0, 0x4c, 0xd0, 0xa2, 0x05, + 0x8d, 0xcd, 0xc1, 0xd6, 0xfa, 0xb3, 0x1d, 0x14, 0x15, 0x80, 0xfa, 0x70, 0x7b, 0xf7, 0xd1, 0xce, + 0x80, 0xaf, 0xb5, 0xb3, 0x3d, 0x1c, 0x75, 0xcb, 0xfa, 0x1f, 0x94, 0xa0, 0x99, 0x78, 0x32, 0xe2, + 0x7d, 0x74, 0x3e, 0xc8, 0x49, 0x53, 0x96, 0x88, 0x32, 0x42, 0xb9, 0xb0, 0xd5, 0x48, 0xfa, 0xf1, + 0x2d, 0x92, 0x62, 0x4d, 0x7c, 0x1b, 0x02, 0xf2, 0x51, 0x73, 0xa5, 0x90, 0xd0, 0x11, 0x50, 0xb5, + 0x7d, 0x4f, 0x2a, 0x87, 0x99, 0xda, 0x24, 0x83, 0x8e, 0x67, 0xc9, 0x2c, 0x9c, 0x68, 0x10, 0x3c, + 0x8a, 0xf4, 0x98, 0xfd, 0xe8, 0xf4, 0x60, 0xe9, 0x6e, 0xa5, 0xfc, 0x6e, 0xe7, 0x82, 0x92, 0xf2, + 0xf9, 0xa0, 0x24, 0x33, 0x9c, 0xb5, 0x2f, 0x33, 0x9c, 0xfa, 0x9f, 0xd4, 0xa0, 0x63, 0xc8, 0x28, + 0xf6, 0x43, 0xa9, 0xfc, 0xc2, 0x57, 0x3d, 0xa1, 0xeb, 0x00, 0x21, 0x0f, 0xce, 0xb6, 0xd6, 0x14, + 0x86, 0xa3, 0x29, 0xd7, 0xb7, 0x48, 0x76, 0x95, 0x85, 0x4c, 0x61, 0x71, 0x0d, 0xb4, 0x7d, 0xd3, + 0x3a, 0xe6, 0x65, 0xd9, 0x4e, 0x36, 0x19, 0xc1, 0xeb, 0x9a, 0x96, 0x25, 0xa3, 0x68, 0x8c, 0xa2, + 0xc0, 0xd6, 0x52, 0x63, 0xcc, 0x63, 0x79, 0x26, 0xee, 0x03, 0x44, 0xd2, 0x0a, 0x65, 0x4c, 0xdd, + 0x68, 0x33, 0xb5, 0x8d, 0xa5, 0x5f, 0xbe, 0x58, 0x5e, 0xf8, 0xa7, 0x17, 0xcb, 0xda, 0x50, 0x7a, + 0x91, 0x13, 0x3b, 0x27, 0xd2, 0xd0, 0x78, 0x10, 0xce, 0xf8, 0x36, 0xb4, 0x23, 0x19, 0xa1, 0xb1, + 0x1d, 0xc7, 0xfe, 0xb1, 0x64, 0xbf, 0x7c, 0xee, 0xa4, 0x45, 0x35, 0x6e, 0x84, 0xc3, 0x50, 0x11, + 0x99, 0x9e, 0xef, 0x9d, 0x4d, 0xfc, 0x69, 0xa4, 0x2c, 0x4b, 0x86, 0x10, 0xab, 0x70, 0x59, 0x7a, + 0x56, 0x78, 0x16, 0xe0, 0x8d, 0xf0, 0x2c, 0xe3, 0x03, 0xc7, 0x95, 0xca, 0xa1, 0x5f, 0xca, 0xba, + 0x1e, 0xcb, 0xb3, 0x2d, 0xc7, 0x95, 0x78, 0xad, 0x13, 0x73, 0xea, 0xc6, 0x63, 0xca, 0x17, 0x00, + 0x5f, 0x8b, 0x30, 0xeb, 0xb6, 0x1d, 0x8a, 0xdb, 0xb0, 0xc4, 0xdd, 0xa1, 0xef, 0x4a, 0xc7, 0xe6, + 0xc5, 0x5a, 0x34, 0xea, 0x12, 0x75, 0x18, 0x84, 0xa7, 0xa5, 0x56, 0xe1, 0x32, 0x8f, 0xe5, 0x3b, + 0x26, 0xa3, 0x17, 0x79, 0x6b, 0xea, 0x1a, 0xaa, 0x9e, 0xe2, 0xd6, 0x81, 0x19, 0x1f, 0x51, 0x14, + 0x90, 0x6c, 0xfd, 0xd4, 0x8c, 0x8f, 0xd0, 0x2f, 0xe0, 0xee, 0x03, 0x47, 0xba, 0x1c, 0xc5, 0x6b, + 0x06, 0xcf, 0xd8, 0x42, 0x0c, 0xfa, 0x05, 0x6a, 0x80, 0x1f, 0x4e, 0x4c, 0x4e, 0x3f, 0x6a, 0x06, + 0x4f, 0xda, 0x22, 0x14, 0x6e, 0xa1, 0x38, 0xea, 0x4d, 0x27, 0x94, 0x88, 0xac, 0x1a, 0x8a, 0xc7, + 0xbb, 0xd3, 0x89, 0x78, 0x1f, 0xba, 0x8e, 0x67, 0x85, 0x72, 0x22, 0xbd, 0xd8, 0x74, 0xc7, 0x07, + 0xa1, 0x3f, 0xe9, 0x2d, 0xd1, 0xa0, 0x4b, 0x39, 0xfc, 0x56, 0xe8, 0x4f, 0x54, 0xf6, 0x26, 0x30, + 0xc3, 0xd8, 0x31, 0xdd, 0x9e, 0x48, 0xb2, 0x37, 0x4f, 0x19, 0xa1, 0xbf, 0xac, 0x40, 0x33, 0x0d, + 0x2f, 0xef, 0x80, 0x36, 0x49, 0xf4, 0xa3, 0x72, 0x0c, 0xdb, 0x05, 0xa5, 0x69, 0x64, 0xfd, 0xe2, + 0x3a, 0x94, 0x8f, 0x4f, 0x94, 0xae, 0x6e, 0xaf, 0x72, 0x62, 0x3f, 0xd8, 0xff, 0x68, 0xf5, 0xf1, + 0x73, 0xa3, 0x7c, 0x7c, 0xf2, 0x15, 0xde, 0x89, 0x78, 0x0f, 0x2e, 0x59, 0xae, 0x34, 0xbd, 0x71, + 0xe6, 0xcd, 0x90, 0x1c, 0x1a, 0x1d, 0x42, 0x3f, 0x4d, 0x5d, 0x9a, 0x5b, 0x50, 0xb3, 0xa5, 0x1b, + 0x9b, 0xf9, 0xfc, 0xf2, 0x5e, 0x68, 0x5a, 0xae, 0xdc, 0x44, 0xb4, 0xc1, 0xbd, 0xa8, 0xab, 0xd3, + 0x90, 0x2e, 0xa7, 0xab, 0xe7, 0x84, 0x73, 0xa9, 0x1e, 0x80, 0xbc, 0x1e, 0xb8, 0x03, 0x4b, 0xf2, + 0x34, 0x20, 0x03, 0x35, 0x4e, 0x33, 0x18, 0x6c, 0x39, 0xbb, 0x49, 0xc7, 0xc3, 0x24, 0x93, 0xf1, + 0x01, 0xaa, 0x28, 0x7a, 0xa4, 0x24, 0x30, 0xad, 0x35, 0x41, 0x3a, 0xae, 0xf0, 0xec, 0x8d, 0x64, + 0x88, 0x78, 0x1f, 0x34, 0xcb, 0xb6, 0xc6, 0x4c, 0x99, 0x76, 0x76, 0xb6, 0x87, 0x9b, 0x0f, 0x99, + 0x24, 0x4d, 0xcb, 0xb6, 0xd8, 0x8b, 0x2f, 0x84, 0x9a, 0x9d, 0xd7, 0x09, 0x35, 0xf3, 0x46, 0xb8, + 0x5b, 0x30, 0xc2, 0x9f, 0x55, 0x9b, 0x8d, 0x6e, 0x53, 0x7f, 0x1b, 0x9a, 0xc9, 0x46, 0xa8, 0x5a, + 0x23, 0xe9, 0xa9, 0x34, 0x02, 0xa9, 0x56, 0x04, 0x47, 0x91, 0x6e, 0x41, 0xe5, 0xf1, 0xf3, 0x21, + 0x69, 0x58, 0x34, 0x76, 0x35, 0xf2, 0x8d, 0xa8, 0x9d, 0x6a, 0xdd, 0x72, 0x4e, 0xeb, 0xde, 0x60, + 0x83, 0x45, 0x0c, 0x4a, 0x72, 0xaf, 0x39, 0x0c, 0x92, 0x98, 0x8d, 0x75, 0x95, 0xd3, 0xb2, 0x04, + 0xe8, 0xff, 0x5e, 0x81, 0x86, 0xf2, 0xa7, 0xd0, 0x48, 0x4d, 0xd3, 0xb4, 0x21, 0x36, 0x8b, 0x81, + 0x6e, 0xea, 0x98, 0xe5, 0x6b, 0x37, 0x95, 0x2f, 0xaf, 0xdd, 0x88, 0x4f, 0x60, 0x31, 0xe0, 0xbe, + 0xbc, 0x2b, 0xf7, 0x66, 0x7e, 0x8e, 0xfa, 0xa5, 0x79, 0xad, 0x20, 0x03, 0x90, 0x94, 0x94, 0xc0, + 0x8e, 0xcd, 0x43, 0x45, 0x81, 0x06, 0xc2, 0x23, 0xf3, 0xf0, 0xb5, 0xfc, 0xb2, 0x0e, 0x39, 0x78, + 0x8b, 0xa4, 0xe0, 0xd1, 0x97, 0xcb, 0x73, 0xa6, 0x5d, 0x74, 0x8f, 0xae, 0x81, 0x66, 0xf9, 0x93, + 0x89, 0x43, 0x7d, 0x1d, 0x95, 0x26, 0x23, 0xc4, 0x28, 0xd2, 0x7f, 0xb7, 0x04, 0x0d, 0x75, 0xaf, + 0x73, 0xc6, 0x77, 0x63, 0x7b, 0x77, 0xdd, 0xf8, 0x51, 0xb7, 0x84, 0xce, 0xc5, 0xf6, 0xee, 0xa8, + 0x5b, 0x16, 0x1a, 0xd4, 0xb6, 0x76, 0xf6, 0xd6, 0x47, 0xdd, 0x0a, 0x1a, 0xe4, 0x8d, 0xbd, 0xbd, + 0x9d, 0x6e, 0x55, 0x2c, 0x42, 0x73, 0x73, 0x7d, 0x34, 0x18, 0x6d, 0x3f, 0x19, 0x74, 0x6b, 0x38, + 0xf6, 0xd1, 0x60, 0xaf, 0x5b, 0xc7, 0xc6, 0xb3, 0xed, 0xcd, 0x6e, 0x03, 0xfb, 0x9f, 0xae, 0x0f, + 0x87, 0x3f, 0xd8, 0x33, 0x36, 0xbb, 0x4d, 0x32, 0xea, 0x23, 0x63, 0x7b, 0xf7, 0x51, 0x57, 0xc3, + 0xf6, 0xde, 0xc6, 0x67, 0x83, 0x87, 0xa3, 0x2e, 0xe8, 0x0f, 0xa0, 0x95, 0xa3, 0x15, 0xce, 0x36, + 0x06, 0x5b, 0xdd, 0x05, 0xdc, 0xf2, 0xf9, 0xfa, 0xce, 0x33, 0xf4, 0x01, 0x3a, 0x00, 0xd4, 0x1c, + 0xef, 0xac, 0xef, 0x3e, 0xea, 0x96, 0x95, 0x07, 0xf9, 0x7d, 0x68, 0x3e, 0x73, 0xec, 0x0d, 0xd7, + 0xb7, 0x8e, 0x51, 0x7c, 0xf6, 0xcd, 0x48, 0x2a, 0x79, 0xa3, 0x36, 0xfa, 0xeb, 0xf4, 0x68, 0x23, + 0xc5, 0x6b, 0x05, 0x21, 0xc5, 0xbc, 0xe9, 0x64, 0x4c, 0xf5, 0xbd, 0x0a, 0x1b, 0x4a, 0x6f, 0x3a, + 0x79, 0xe6, 0xd8, 0x91, 0x7e, 0x0c, 0x8d, 0x67, 0x8e, 0xfd, 0xd4, 0xb4, 0x8e, 0x49, 0x4d, 0xe2, + 0xd2, 0xe3, 0xc8, 0xf9, 0x5c, 0x2a, 0x83, 0xaa, 0x11, 0x66, 0xe8, 0x7c, 0x2e, 0xc5, 0x3b, 0x50, + 0x27, 0x20, 0x49, 0x71, 0xd0, 0x53, 0x4b, 0x8e, 0x63, 0xa8, 0x3e, 0x2a, 0xaf, 0xb9, 0xae, 0x6f, + 0x8d, 0x43, 0x79, 0xd0, 0x7b, 0x93, 0x39, 0x40, 0x08, 0x43, 0x1e, 0xe8, 0xbf, 0x5f, 0x4a, 0x6f, + 0x4e, 0x55, 0x9c, 0x65, 0xa8, 0x06, 0xa6, 0x75, 0xac, 0xfc, 0x99, 0x96, 0x5a, 0x10, 0x0f, 0x63, + 0x50, 0x87, 0x78, 0x0f, 0x9a, 0x4a, 0x90, 0x92, 0x5d, 0x5b, 0x39, 0x89, 0x33, 0xd2, 0xce, 0x22, + 0xe3, 0x2b, 0x45, 0xc6, 0x53, 0x34, 0x1c, 0xb8, 0x4e, 0xcc, 0xcf, 0x06, 0x1f, 0x27, 0x41, 0xfa, + 0x47, 0x00, 0x59, 0x41, 0x6d, 0x8e, 0x7b, 0x77, 0x05, 0x6a, 0xa6, 0xeb, 0x98, 0x49, 0x74, 0xcd, + 0x80, 0xbe, 0x0b, 0xad, 0x5c, 0x19, 0x0e, 0x69, 0x6b, 0xba, 0x2e, 0xda, 0x58, 0x7e, 0xfb, 0x4d, + 0xa3, 0x61, 0xba, 0xee, 0x63, 0x79, 0x16, 0xa1, 0x6b, 0xcd, 0x15, 0xbc, 0xf2, 0x4c, 0x91, 0x87, + 0xa6, 0x1a, 0xdc, 0xa9, 0x7f, 0x00, 0xf5, 0xad, 0x24, 0x00, 0x49, 0x1e, 0x43, 0xe9, 0xa2, 0xc7, + 0xa0, 0x7f, 0xac, 0xce, 0x4c, 0x75, 0x22, 0x71, 0x47, 0x55, 0x0a, 0x23, 0xae, 0x4b, 0x96, 0xb2, + 0xfc, 0x0c, 0x0f, 0x52, 0x45, 0x42, 0x1a, 0xac, 0x6f, 0x42, 0xf3, 0x95, 0xb5, 0x57, 0x45, 0x80, + 0x72, 0x46, 0x80, 0x39, 0xd5, 0x58, 0xfd, 0x27, 0x00, 0x59, 0x45, 0x51, 0xbd, 0x4d, 0x5e, 0x05, + 0xdf, 0xe6, 0x6d, 0x68, 0x5a, 0x47, 0x8e, 0x6b, 0x87, 0xd2, 0x2b, 0xdc, 0x3a, 0xab, 0x41, 0xa6, + 0xfd, 0xe2, 0x26, 0x54, 0xa9, 0x50, 0x5a, 0xc9, 0x34, 0x77, 0x5a, 0x25, 0xa5, 0x1e, 0xfd, 0x14, + 0xda, 0x1c, 0xb3, 0xbc, 0x86, 0xc7, 0x57, 0x54, 0x9d, 0xe5, 0x73, 0xaa, 0xf3, 0x2a, 0xd4, 0xc9, + 0x85, 0x48, 0x6e, 0xa3, 0xa0, 0x0b, 0x54, 0xea, 0x1f, 0x95, 0x01, 0x78, 0xeb, 0x5d, 0xdf, 0x96, + 0xc5, 0xe4, 0x40, 0x69, 0x36, 0x39, 0x20, 0xa0, 0x9a, 0xd6, 0xc0, 0x35, 0x83, 0xda, 0x99, 0x31, + 0x54, 0x09, 0x03, 0x36, 0x86, 0x6f, 0x81, 0x46, 0x5e, 0x9e, 0xf3, 0x39, 0x15, 0x60, 0x70, 0xc3, + 0x0c, 0x91, 0xaf, 0x08, 0xd7, 0x8a, 0x15, 0xe1, 0xb4, 0x3c, 0x56, 0xe7, 0xd5, 0xb8, 0x3c, 0x36, + 0xa7, 0xd2, 0xc7, 0x19, 0x9b, 0x48, 0x86, 0x71, 0x92, 0x6e, 0x60, 0x28, 0x8d, 0x9c, 0x35, 0x35, + 0xd6, 0xe4, 0x9c, 0x8b, 0xe7, 0x8f, 0x2d, 0xdf, 0x3b, 0x70, 0x1d, 0x2b, 0x56, 0x15, 0x60, 0xf0, + 0xfc, 0x87, 0x0a, 0x43, 0x8b, 0x79, 0xce, 0x4f, 0xa7, 0xec, 0xec, 0xe1, 0x62, 0x04, 0xe9, 0x9f, + 0xc0, 0x62, 0xc2, 0x17, 0x2a, 0xb4, 0xdd, 0x4e, 0xa3, 0xcd, 0x52, 0xc6, 0xf3, 0x8c, 0x7c, 0x1b, + 0xe5, 0x5e, 0x29, 0x89, 0x37, 0xf5, 0xdf, 0xab, 0x26, 0x93, 0x55, 0x3d, 0xe8, 0xd5, 0xb4, 0x2d, + 0x26, 0x10, 0xca, 0xaf, 0x95, 0x40, 0xf8, 0x0e, 0x68, 0x36, 0xc5, 0xc4, 0xce, 0x49, 0x62, 0xdc, + 0xfa, 0xb3, 0xf1, 0xaf, 0x8a, 0x9a, 0xc9, 0x1b, 0x4f, 0x07, 0x7f, 0x09, 0x7f, 0x52, 0x2e, 0xd4, + 0xe6, 0x71, 0xa1, 0xfe, 0x35, 0xb9, 0x90, 0x11, 0xb9, 0x93, 0x27, 0x32, 0x3a, 0xb6, 0x9e, 0xef, + 0x8d, 0xbd, 0xa9, 0xeb, 0x9a, 0xfb, 0xae, 0x54, 0xec, 0x69, 0x79, 0xbe, 0xb7, 0xab, 0x50, 0xe8, + 0x97, 0xe7, 0x87, 0xb0, 0x12, 0x60, 0x56, 0x5d, 0xca, 0x8d, 0x23, 0x55, 0xb1, 0x02, 0x5d, 0x7f, + 0xff, 0x27, 0xd2, 0x8a, 0x89, 0x92, 0x63, 0x7a, 0xfd, 0xec, 0x94, 0x77, 0x18, 0x8f, 0xa4, 0xdb, + 0x45, 0x3d, 0x30, 0x23, 0x16, 0xed, 0x59, 0xb1, 0xd0, 0x3f, 0x06, 0x2d, 0xa5, 0x5e, 0x2e, 0x2e, + 0xd7, 0xa0, 0xb6, 0xbd, 0xbb, 0x39, 0xf8, 0x61, 0xb7, 0x84, 0xe6, 0xd5, 0x18, 0x3c, 0x1f, 0x18, + 0xc3, 0x41, 0xb7, 0x8c, 0xa6, 0x6f, 0x73, 0xb0, 0x33, 0x18, 0x0d, 0xba, 0x15, 0x76, 0x9d, 0xa8, + 0x5c, 0xe3, 0x3a, 0x96, 0x13, 0xeb, 0x43, 0x80, 0x2c, 0xd9, 0x80, 0x5a, 0x3c, 0x3b, 0x9c, 0xca, + 0x76, 0xc6, 0xc9, 0xb1, 0x56, 0xd2, 0x07, 0x5c, 0xbe, 0x28, 0xa5, 0xc1, 0xfd, 0xfa, 0x1a, 0x68, + 0x4f, 0xcc, 0xe0, 0x53, 0x2e, 0x6c, 0xde, 0x82, 0x0e, 0xf9, 0xeb, 0x49, 0x24, 0xc4, 0xca, 0x75, + 0xd1, 0x68, 0xa7, 0x58, 0xd4, 0xd5, 0xfa, 0x5f, 0x94, 0xe0, 0xca, 0x13, 0xff, 0x44, 0xa6, 0xfe, + 0xf1, 0x53, 0xf3, 0xcc, 0xf5, 0x4d, 0xfb, 0x4b, 0xc4, 0xf3, 0x3a, 0x40, 0xe4, 0x4f, 0xa9, 0xd0, + 0x98, 0x94, 0x65, 0x0d, 0x8d, 0x31, 0x8f, 0xd4, 0xf7, 0x24, 0x32, 0x8a, 0xa9, 0x53, 0x19, 0x5e, + 0x84, 0xb1, 0xeb, 0x0d, 0xa8, 0xc7, 0xa7, 0x5e, 0x56, 0x24, 0xae, 0xc5, 0x94, 0xa5, 0x9f, 0xeb, + 0x2e, 0xd7, 0xe6, 0xbb, 0xcb, 0xfa, 0x43, 0xd0, 0x46, 0xa7, 0x94, 0xa7, 0x9e, 0x16, 0x1d, 0xd6, + 0xd2, 0x2b, 0xdc, 0xa2, 0xf2, 0x8c, 0x5b, 0xf4, 0x6f, 0x25, 0x68, 0xe5, 0xfc, 0x7e, 0xf1, 0x4d, + 0xa8, 0xc6, 0xa7, 0x5e, 0xf1, 0x5b, 0x8c, 0x64, 0x13, 0x83, 0xba, 0xce, 0xe5, 0x62, 0xcb, 0xe7, + 0x72, 0xb1, 0x62, 0x07, 0x2e, 0xb1, 0xa6, 0x4e, 0x2e, 0x91, 0xa4, 0xac, 0xde, 0x9e, 0x89, 0x33, + 0x38, 0x97, 0x9f, 0x5c, 0x49, 0xe5, 0x61, 0x3a, 0x87, 0x05, 0x64, 0x7f, 0x1d, 0x2e, 0xcf, 0x19, + 0xf6, 0x55, 0xaa, 0x3a, 0xfa, 0x32, 0xb4, 0x47, 0xa7, 0xde, 0xc8, 0x99, 0xc8, 0x28, 0x36, 0x27, + 0x01, 0xb9, 0x95, 0xca, 0xd2, 0x56, 0x8d, 0x72, 0x1c, 0xe9, 0xef, 0xc2, 0xe2, 0x53, 0x29, 0x43, + 0x43, 0x46, 0x81, 0xef, 0xb1, 0x33, 0xa5, 0x72, 0xe8, 0x6c, 0xd6, 0x15, 0xa4, 0xff, 0x36, 0x68, + 0x86, 0x79, 0x10, 0x6f, 0x98, 0xb1, 0x75, 0xf4, 0x55, 0x92, 0x32, 0xef, 0x42, 0x23, 0x60, 0x99, + 0x52, 0xd1, 0xe0, 0x22, 0x99, 0x77, 0x25, 0x67, 0x46, 0xd2, 0xa9, 0x7f, 0x1b, 0x3a, 0xaa, 0xa0, + 0x95, 0x9c, 0x24, 0x57, 0xf5, 0x2a, 0x5d, 0x58, 0xf5, 0xd2, 0x0f, 0xa1, 0x9d, 0xcc, 0x63, 0x63, + 0xf9, 0x5a, 0xd3, 0xbe, 0xfa, 0x67, 0x05, 0xfa, 0x6f, 0xc1, 0xe5, 0xe1, 0x74, 0x3f, 0xb2, 0x42, + 0x87, 0x72, 0x08, 0xc9, 0x76, 0x7d, 0x68, 0x06, 0xa1, 0x3c, 0x70, 0x4e, 0x65, 0xf2, 0xc4, 0x52, + 0x58, 0xdc, 0x86, 0xc6, 0x04, 0xe9, 0x25, 0xb3, 0xc7, 0x9b, 0xc5, 0xb8, 0x4f, 0xb0, 0xc7, 0x48, + 0x06, 0xe8, 0xdf, 0x85, 0x2b, 0xc5, 0xe5, 0x15, 0x15, 0xde, 0x86, 0xca, 0xf1, 0x49, 0xa4, 0xc8, + 0xbc, 0x54, 0x88, 0x91, 0xe9, 0x7b, 0x0e, 0xec, 0xd5, 0xff, 0xa6, 0x04, 0x15, 0x8c, 0xe9, 0x73, + 0x1f, 0xab, 0x55, 0xf9, 0x63, 0xb5, 0x6b, 0xf9, 0x7c, 0x3b, 0xc7, 0x5c, 0x59, 0x5e, 0xfd, 0x2d, + 0xd0, 0x0e, 0xfc, 0xf0, 0x67, 0x66, 0x68, 0x4b, 0x5b, 0x59, 0xec, 0x0c, 0x41, 0xae, 0xf6, 0x74, + 0x12, 0x28, 0xb5, 0x4f, 0x6d, 0x71, 0x4b, 0xd9, 0x7c, 0x8e, 0x83, 0x96, 0x90, 0xb2, 0xbb, 0xd3, + 0xc9, 0xaa, 0x2b, 0xcd, 0x88, 0x8c, 0x10, 0xbb, 0x01, 0xfa, 0x1d, 0xd0, 0x52, 0x14, 0x2a, 0xc8, + 0xdd, 0xe1, 0x78, 0x7b, 0x93, 0x73, 0x98, 0x18, 0x31, 0x94, 0x50, 0x39, 0x8e, 0x7e, 0xb8, 0x3b, + 0x1e, 0x0d, 0xbb, 0x65, 0xfd, 0xc7, 0xd0, 0x4a, 0xde, 0xcf, 0xb6, 0x4d, 0x05, 0x3b, 0x7a, 0xc0, + 0xdb, 0x76, 0xe1, 0x3d, 0x6f, 0x53, 0x48, 0x27, 0x3d, 0x7b, 0x3b, 0x79, 0x78, 0x0c, 0x14, 0x6f, + 0xa8, 0xaa, 0x7f, 0xc9, 0x0d, 0xf5, 0x01, 0x2c, 0x19, 0x54, 0x78, 0x40, 0x83, 0x9c, 0xb0, 0xec, + 0x2a, 0xd4, 0x3d, 0xdf, 0x96, 0xe9, 0x06, 0x0a, 0xc2, 0x9d, 0x15, 0xb3, 0x95, 0x4a, 0x4b, 0x79, + 0x2f, 0x61, 0x09, 0xb5, 0x64, 0x51, 0xd0, 0x0a, 0x49, 0xf1, 0xd2, 0x4c, 0x52, 0x1c, 0x37, 0x51, + 0xf5, 0x6f, 0xf6, 0x8f, 0x92, 0x9a, 0x77, 0x1f, 0x9a, 0x76, 0x14, 0xd3, 0xb3, 0x56, 0xba, 0x31, + 0x85, 0xf5, 0x7b, 0x70, 0x79, 0x3d, 0x08, 0xdc, 0xb3, 0xa4, 0x5a, 0xa8, 0x36, 0xea, 0x65, 0x25, + 0xc5, 0x92, 0x8a, 0x23, 0x19, 0xd4, 0xb7, 0x60, 0x31, 0xc9, 0x48, 0x3c, 0x91, 0xb1, 0x49, 0x1a, + 0xcf, 0x75, 0x0a, 0x21, 0x79, 0x93, 0x11, 0xa3, 0x62, 0xea, 0x7d, 0xe6, 0x7e, 0xab, 0x50, 0x57, + 0xea, 0x54, 0x40, 0xd5, 0xf2, 0x6d, 0xde, 0xa8, 0x66, 0x50, 0x1b, 0xa5, 0x6a, 0x12, 0x1d, 0x26, + 0x1e, 0xf2, 0x24, 0x3a, 0xd4, 0xff, 0xab, 0x0c, 0xed, 0x0d, 0xca, 0x24, 0x25, 0x67, 0xcc, 0x65, + 0x59, 0x4b, 0x85, 0x2c, 0x6b, 0x3e, 0xa3, 0x5a, 0x2e, 0x64, 0x54, 0x0b, 0x07, 0xaa, 0x14, 0xdd, + 0xda, 0x37, 0xa1, 0x31, 0xf5, 0x9c, 0xd3, 0xc4, 0x4e, 0x68, 0xe4, 0x1e, 0x9c, 0x8e, 0x22, 0x71, + 0x13, 0x5a, 0x68, 0x4a, 0x1c, 0x8f, 0xb3, 0x98, 0x9c, 0x8a, 0xcc, 0xa3, 0x66, 0x72, 0x95, 0xf5, + 0x57, 0xe7, 0x2a, 0x1b, 0x5f, 0x27, 0x57, 0xd9, 0xfc, 0x1a, 0xb9, 0x4a, 0x6d, 0x36, 0x57, 0x59, + 0x74, 0xdc, 0xe1, 0x9c, 0xe3, 0x7e, 0x1d, 0x80, 0x3f, 0xe5, 0x39, 0x98, 0xba, 0xae, 0xf2, 0x6e, + 0x34, 0xc2, 0x6c, 0x4d, 0x5d, 0x57, 0xdf, 0x81, 0x4e, 0xc2, 0x00, 0xa5, 0x28, 0x3e, 0x81, 0x4b, + 0xaa, 0x56, 0x21, 0x43, 0x95, 0x7e, 0x63, 0xfd, 0x47, 0xaf, 0x94, 0xcb, 0x09, 0xaa, 0xc7, 0xe8, + 0xd8, 0x79, 0x30, 0xd2, 0x7f, 0x51, 0x82, 0x76, 0x61, 0x84, 0x78, 0x90, 0x55, 0x3e, 0x4a, 0xf4, + 0xd6, 0x7b, 0xe7, 0x56, 0x79, 0x75, 0xf5, 0xa3, 0x3c, 0x53, 0xfd, 0xd0, 0xef, 0xa6, 0x35, 0x0d, + 0x55, 0xc9, 0x58, 0x48, 0x2b, 0x19, 0x94, 0xfc, 0x5f, 0x1f, 0x8d, 0x8c, 0x6e, 0x59, 0xd4, 0xa1, + 0xbc, 0x3b, 0xec, 0x56, 0xf4, 0x5f, 0x97, 0xa1, 0x3d, 0x38, 0x0d, 0xe8, 0xb3, 0xb6, 0x2f, 0x8d, + 0x82, 0x72, 0xd2, 0x57, 0x2e, 0x48, 0x5f, 0x4e, 0x8e, 0x2a, 0xaa, 0x94, 0xcb, 0x72, 0x84, 0x71, + 0x11, 0x67, 0x4e, 0x95, 0x7c, 0x31, 0xf4, 0x7f, 0x47, 0xbe, 0x0a, 0xda, 0x09, 0x66, 0x4b, 0x76, + 0x3b, 0xd0, 0x49, 0x88, 0xab, 0xc4, 0xe7, 0xb5, 0x1e, 0x3e, 0x7f, 0xee, 0xea, 0xa6, 0x49, 0x3a, + 0x06, 0xf4, 0x3f, 0x2b, 0x83, 0xc6, 0xd2, 0x88, 0xf7, 0x79, 0x5f, 0xd9, 0x88, 0x52, 0x56, 0x1d, + 0x4a, 0x3b, 0x57, 0x1f, 0xcb, 0xb3, 0xcc, 0x4e, 0xcc, 0xad, 0xa8, 0xaa, 0x54, 0x1e, 0x67, 0x33, + 0x28, 0x95, 0x77, 0x0d, 0x34, 0x76, 0xf1, 0xa6, 0xaa, 0x34, 0x51, 0x35, 0xd8, 0xe7, 0x7b, 0xe6, + 0x90, 0x95, 0x8a, 0x65, 0x38, 0x51, 0x9c, 0xa2, 0x76, 0x31, 0x6e, 0x6c, 0x27, 0x11, 0x4b, 0x81, + 0x22, 0x8d, 0x59, 0x8a, 0x1c, 0x41, 0x43, 0x9d, 0x0d, 0xdd, 0xf8, 0x67, 0xbb, 0x8f, 0x77, 0xf7, + 0x7e, 0xb0, 0x5b, 0x90, 0xd1, 0xd4, 0xd1, 0x2f, 0xe7, 0x1d, 0xfd, 0x0a, 0xe2, 0x1f, 0xee, 0x3d, + 0xdb, 0x1d, 0x75, 0xab, 0xa2, 0x0d, 0x1a, 0x35, 0xc7, 0xc6, 0xe0, 0x79, 0xb7, 0x46, 0x99, 0xb0, + 0x87, 0x9f, 0x0e, 0x9e, 0xac, 0x77, 0xeb, 0x69, 0xad, 0xae, 0xa1, 0xff, 0x69, 0x09, 0x96, 0x98, + 0x20, 0xf9, 0xa4, 0x50, 0xfe, 0x43, 0xf4, 0x2a, 0x7f, 0x88, 0xfe, 0xbf, 0x9b, 0x07, 0xc2, 0x49, + 0x53, 0x27, 0xa9, 0x8e, 0x73, 0x82, 0xb2, 0x39, 0x75, 0x54, 0x51, 0xfc, 0xef, 0x4b, 0xd0, 0xe7, + 0xf8, 0xe2, 0x51, 0x68, 0x06, 0x47, 0xdf, 0xdf, 0x39, 0x97, 0x91, 0xb8, 0xc8, 0xeb, 0xbe, 0x05, + 0x1d, 0xfa, 0x54, 0xff, 0xa7, 0xee, 0x58, 0x45, 0xc7, 0xcc, 0xdd, 0xb6, 0xc2, 0xf2, 0x42, 0xe2, + 0x43, 0x58, 0xe4, 0x4f, 0xfa, 0x29, 0x63, 0x5f, 0xa8, 0xec, 0x16, 0xa2, 0x9b, 0x16, 0x8f, 0xe2, + 0x3a, 0xf4, 0x83, 0x74, 0x52, 0x96, 0xbc, 0x38, 0x5f, 0xbc, 0x55, 0x53, 0x46, 0x94, 0xd2, 0xb8, + 0x07, 0xd7, 0xe6, 0xde, 0x43, 0x89, 0x7d, 0x2e, 0x71, 0xcc, 0xd2, 0xa6, 0xff, 0xba, 0x04, 0xcd, + 0x8d, 0xa9, 0x7b, 0x4c, 0x06, 0xf5, 0x3a, 0x80, 0xb4, 0x0f, 0xa5, 0xfa, 0x36, 0xbe, 0x44, 0x2a, + 0x44, 0x43, 0x0c, 0x7f, 0x1d, 0xff, 0x09, 0x00, 0xdf, 0x71, 0x3c, 0x31, 0x03, 0xc5, 0x22, 0xaa, + 0xb4, 0x26, 0x0b, 0xa8, 0xbb, 0x3c, 0x31, 0x03, 0x55, 0x69, 0x8d, 0x12, 0x38, 0xab, 0x40, 0x57, + 0x5e, 0x51, 0x81, 0xee, 0xef, 0x42, 0xa7, 0xb8, 0xc4, 0x9c, 0x84, 0xdd, 0xbb, 0xc5, 0xaf, 0x7c, + 0xce, 0xd3, 0x30, 0x17, 0x0f, 0x7c, 0x06, 0x97, 0x66, 0x92, 0xff, 0xaf, 0xd2, 0xab, 0x85, 0x27, + 0x53, 0x9e, 0x7d, 0x32, 0x1f, 0xc0, 0xd2, 0xc8, 0x8c, 0x8e, 0x55, 0x8c, 0x94, 0x39, 0x02, 0xb1, + 0x19, 0x1d, 0x8f, 0x53, 0xa2, 0xd6, 0x11, 0xdc, 0xb6, 0xf5, 0x07, 0x20, 0xf2, 0xa3, 0x15, 0xfd, + 0x31, 0xf6, 0xc5, 0xe1, 0x13, 0x19, 0x9b, 0x89, 0xc7, 0x82, 0x08, 0x24, 0xde, 0xda, 0xdf, 0x95, + 0xa0, 0x8a, 0x41, 0x85, 0xb8, 0x0b, 0xda, 0xa7, 0xd2, 0x0c, 0xe3, 0x7d, 0x69, 0xc6, 0xa2, 0x10, + 0x40, 0xf4, 0x89, 0x6e, 0xd9, 0x97, 0x43, 0xfa, 0xc2, 0xfd, 0x92, 0x58, 0xe5, 0xef, 0x9a, 0x93, + 0xef, 0xb5, 0xdb, 0x49, 0x70, 0x42, 0xc1, 0x4b, 0xbf, 0x30, 0x5f, 0x5f, 0x58, 0xa1, 0xf1, 0x9f, + 0xf9, 0x8e, 0xf7, 0x90, 0xbf, 0xa6, 0x15, 0xb3, 0xc1, 0xcc, 0xec, 0x0c, 0x71, 0x17, 0xea, 0xdb, + 0x11, 0x46, 0x4d, 0xe7, 0x87, 0x12, 0xf1, 0xf3, 0x01, 0x95, 0xbe, 0xb0, 0xf6, 0x97, 0x35, 0xa8, + 0xfe, 0x58, 0x86, 0xbe, 0xf8, 0x00, 0x1a, 0xea, 0x3b, 0x2b, 0x91, 0xfb, 0x9e, 0xaa, 0x4f, 0x89, + 0x9d, 0x99, 0x0f, 0xb0, 0x68, 0x97, 0x2e, 0xf3, 0x2f, 0x2b, 0x79, 0x89, 0xec, 0x33, 0xb0, 0x73, + 0x87, 0xfa, 0x18, 0xba, 0xc3, 0x38, 0x94, 0xe6, 0x24, 0x37, 0xbc, 0x48, 0xaa, 0x79, 0xf5, 0x33, + 0xa2, 0xd7, 0x1d, 0xa8, 0x73, 0x68, 0x3a, 0x33, 0x61, 0xb6, 0x38, 0x46, 0x83, 0xdf, 0x83, 0xd6, + 0xf0, 0xc8, 0x9f, 0xba, 0xf6, 0x50, 0x86, 0x27, 0x52, 0xe4, 0xa2, 0xab, 0x7e, 0xae, 0xad, 0x2f, + 0x88, 0x07, 0x50, 0x47, 0x8e, 0x84, 0x13, 0xb1, 0x94, 0x8b, 0xc0, 0x58, 0x4c, 0xfa, 0x22, 0x8f, + 0x4a, 0x28, 0x25, 0xde, 0x03, 0x8d, 0x43, 0x01, 0x0c, 0x04, 0x1a, 0x2a, 0xba, 0xe0, 0x63, 0xe4, + 0x42, 0x04, 0x7d, 0x41, 0xac, 0x00, 0xe4, 0x62, 0xda, 0x57, 0x8d, 0xfc, 0x10, 0xda, 0x0f, 0x49, + 0x13, 0xee, 0x85, 0xeb, 0xfb, 0x7e, 0x18, 0x8b, 0xd9, 0x6f, 0x3f, 0xfb, 0xb3, 0x08, 0x7d, 0x01, + 0xa3, 0xc3, 0x51, 0x78, 0xc6, 0xe3, 0x97, 0x54, 0x2a, 0x20, 0xdb, 0x6f, 0x0e, 0x5d, 0xc4, 0x47, + 0xe9, 0xbb, 0x4a, 0x23, 0x80, 0x79, 0x95, 0x36, 0x26, 0x11, 0xbf, 0x01, 0x22, 0x11, 0x64, 0xe1, + 0x89, 0x78, 0x83, 0xab, 0x7e, 0x33, 0xe1, 0xca, 0xf9, 0x29, 0x59, 0x28, 0xc2, 0x53, 0xce, 0x85, + 0x26, 0x33, 0x53, 0xbe, 0x05, 0x8b, 0xf9, 0xb0, 0x42, 0x50, 0xf9, 0x6a, 0x4e, 0xa0, 0x51, 0x9c, + 0xb6, 0xf6, 0x1f, 0x35, 0xa8, 0xff, 0xc0, 0x0f, 0x8f, 0x65, 0x28, 0x6e, 0x43, 0x9d, 0xea, 0xb7, + 0xea, 0x2d, 0xa5, 0xb5, 0xdc, 0x79, 0xb4, 0x7b, 0x07, 0x34, 0x92, 0x0c, 0x7c, 0xec, 0x2c, 0xaf, + 0xf4, 0x5f, 0x25, 0x5e, 0x9c, 0x33, 0xa7, 0x24, 0xdc, 0x1d, 0x96, 0xd6, 0xf4, 0x7b, 0x8a, 0x42, + 0x7d, 0xb5, 0x4f, 0x2c, 0x7d, 0xfc, 0x7c, 0x88, 0xef, 0xf3, 0x7e, 0x09, 0x7d, 0x8a, 0x21, 0x33, + 0x0f, 0x07, 0x65, 0xff, 0xc5, 0xe0, 0xe7, 0x9f, 0xfd, 0xf9, 0x41, 0x5f, 0x10, 0xf7, 0xa0, 0xae, + 0x4c, 0xcc, 0x52, 0xa6, 0x08, 0x93, 0x1b, 0x76, 0xf3, 0x28, 0x35, 0xe1, 0x01, 0xd4, 0xd9, 0x1c, + 0xf3, 0x84, 0x42, 0x5c, 0xc3, 0x72, 0x5a, 0xf4, 0xb4, 0xf5, 0x05, 0x71, 0x07, 0x1a, 0xaa, 0x3a, + 0x2b, 0xe6, 0x94, 0x6a, 0xcf, 0x71, 0xac, 0xce, 0xbe, 0x16, 0xaf, 0x5f, 0x70, 0x6a, 0x79, 0xfd, + 0xa2, 0x2b, 0xc6, 0x4f, 0xdf, 0x90, 0x96, 0x74, 0x72, 0x89, 0x39, 0x91, 0x50, 0x64, 0x8e, 0xfe, + 0xfa, 0x18, 0xda, 0x85, 0x24, 0x9e, 0xe8, 0x25, 0x62, 0x31, 0x9b, 0xd7, 0x3b, 0xa7, 0x35, 0xbe, + 0x0b, 0x9a, 0x4a, 0x3b, 0xec, 0x2b, 0xc1, 0x98, 0x93, 0xe4, 0xe8, 0x9f, 0xcf, 0x3b, 0x90, 0x2a, + 0xf8, 0x21, 0x5c, 0x9e, 0x63, 0x5b, 0x05, 0x7d, 0xcd, 0x7b, 0xb1, 0xf3, 0xd0, 0x5f, 0xbe, 0xb0, + 0x3f, 0x25, 0xc0, 0xd7, 0x7b, 0x4e, 0xdf, 0x03, 0xc8, 0x4c, 0x0c, 0xbf, 0x8d, 0x73, 0x06, 0xaa, + 0x7f, 0x75, 0x16, 0x9d, 0x6c, 0xba, 0xd1, 0xfb, 0xe5, 0x17, 0x37, 0x4a, 0xbf, 0xfa, 0xe2, 0x46, + 0xe9, 0x5f, 0xbf, 0xb8, 0x51, 0xfa, 0xc5, 0x6f, 0x6e, 0x2c, 0xfc, 0xea, 0x37, 0x37, 0x16, 0xfe, + 0xf1, 0x37, 0x37, 0x16, 0xf6, 0xeb, 0xf4, 0xa7, 0xc1, 0x0f, 0xff, 0x3b, 0x00, 0x00, 0xff, 0xff, + 0x0a, 0xb1, 0x62, 0xd8, 0xaa, 0x38, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -10190,6 +10207,16 @@ func (m *SchemaNode) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Unique { + i-- + if m.Unique { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x58 + } if m.NoConflict { i-- if m.NoConflict { @@ -10343,6 +10370,16 @@ func (m *SchemaUpdate) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Unique { + i-- + if m.Unique { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x70 + } if m.NoConflict { i-- if m.NoConflict { @@ -13163,6 +13200,9 @@ func (m *SchemaNode) Size() (n int) { if m.NoConflict { n += 2 } + if m.Unique { + n += 2 + } return n } @@ -13228,6 +13268,9 @@ func (m *SchemaUpdate) Size() (n int) { if m.NoConflict { n += 2 } + if m.Unique { + n += 2 + } return n } @@ -22135,6 +22178,26 @@ func (m *SchemaNode) Unmarshal(dAtA []byte) error { } } m.NoConflict = bool(v != 0) + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Unique", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Unique = bool(v != 0) default: iNdEx = preIndex skippy, err := skipPb(dAtA[iNdEx:]) @@ -22543,6 +22606,26 @@ func (m *SchemaUpdate) Unmarshal(dAtA []byte) error { } } m.NoConflict = bool(v != 0) + case 14: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Unique", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Unique = bool(v != 0) default: iNdEx = preIndex skippy, err := skipPb(dAtA[iNdEx:]) diff --git a/schema/parse.go b/schema/parse.go index a200b4d5542..29b85942a14 100644 --- a/schema/parse.go +++ b/schema/parse.go @@ -73,6 +73,8 @@ func parseDirective(it *lex.ItemIterator, schema *pb.SchemaUpdate, t types.TypeI schema.Count = true case "upsert": schema.Upsert = true + case "unique": + schema.Unique = true case "noconflict": schema.NoConflict = true case "lang": diff --git a/schema/schema.go b/schema/schema.go index a1da73cd202..e04d67649aa 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -49,12 +49,12 @@ var ( type contextKey int const ( - isWrite contextKey = iota + IsWrite contextKey = iota ) // GetWriteContext returns a context that sets the schema context for writing. func GetWriteContext(ctx context.Context) context.Context { - return context.WithValue(ctx, isWrite, true) + return context.WithValue(ctx, IsWrite, true) } func (s *state) init() { @@ -248,7 +248,7 @@ func (s *state) SetType(typeName string, typ *pb.TypeUpdate) { // Get gets the schema for the given predicate. func (s *state) Get(ctx context.Context, pred string) (pb.SchemaUpdate, bool) { - isWrite, _ := ctx.Value(isWrite).(bool) + isWrite, _ := ctx.Value(IsWrite).(bool) s.RLock() defer s.RUnlock() // If this is write context, mutSchema will have the updated schema. @@ -289,7 +289,7 @@ func (s *state) TypeOf(pred string) (types.TypeID, error) { // IsIndexed returns whether the predicate is indexed or not func (s *state) IsIndexed(ctx context.Context, pred string) bool { - isWrite, _ := ctx.Value(isWrite).(bool) + isWrite, _ := ctx.Value(IsWrite).(bool) s.RLock() defer s.RUnlock() if isWrite { @@ -338,7 +338,7 @@ func (s *state) Types() []string { // Tokenizer returns the tokenizer for given predicate func (s *state) Tokenizer(ctx context.Context, pred string) []tok.Tokenizer { - isWrite, _ := ctx.Value(isWrite).(bool) + isWrite, _ := ctx.Value(IsWrite).(bool) s.RLock() defer s.RUnlock() var su *pb.SchemaUpdate @@ -390,7 +390,7 @@ func (s *state) HasTokenizer(ctx context.Context, id byte, pred string) bool { // IsReversed returns whether the predicate has reverse edge or not func (s *state) IsReversed(ctx context.Context, pred string) bool { - isWrite, _ := ctx.Value(isWrite).(bool) + isWrite, _ := ctx.Value(IsWrite).(bool) s.RLock() defer s.RUnlock() if isWrite { @@ -406,7 +406,7 @@ func (s *state) IsReversed(ctx context.Context, pred string) bool { // HasCount returns whether we want to mantain a count index for the given predicate or not. func (s *state) HasCount(ctx context.Context, pred string) bool { - isWrite, _ := ctx.Value(isWrite).(bool) + isWrite, _ := ctx.Value(IsWrite).(bool) s.RLock() defer s.RUnlock() if isWrite { diff --git a/systest/unique_test.go b/systest/unique_test.go new file mode 100644 index 00000000000..54c6b3ce1b8 --- /dev/null +++ b/systest/unique_test.go @@ -0,0 +1,760 @@ +//go:build integration + +/* + * Copyright 2023 Dgraph Labs, Inc. and Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//nolint:lll +package main + +import ( + "context" + "encoding/json" + "fmt" + "math/rand" + "strings" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/dgraph-io/dgo/v230/protos/api" + "github.com/dgraph-io/dgraph/dgraph/cmd/live" + "github.com/dgraph-io/dgraph/dgraphtest" +) + +const emailQuery = `{ + q(func: eq(email, "example@email.com")) { + email + } + }` + +const emailQueryWithUid = `{ + q(func: eq(email, "example@email.com")) { + email + uid + } + }` + +func setUpDgraph(t *testing.T) *dgraphtest.GrpcClient { + c := dgraphtest.ComposeCluster{} + dg, close, err := c.Client() + require.NoError(t, err) + defer close() + require.NoError(t, err) + require.NoError(t, dg.Login(context.Background(), "groot", "password")) + require.NoError(t, dg.DropAll()) + return dg +} + +func TestSchema(t *testing.T) { + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(exact) .`)) + resp, err := dg.Query(`schema{ }`) + require.NoError(t, err) + var sch live.Schema + require.NoError(t, json.Unmarshal(resp.GetJson(), &sch)) + for _, pred := range sch.Predicates { + if pred.Predicate == "email" { + require.Equal(t, true, pred.Unique) + } + } + + require.NoError(t, dg.DropAll()) + err = dg.SetupSchema(`email: string @unique .`) + require.Error(t, err) + require.ErrorContains(t, err, "index for predicate [email] is missing,"+ + " add either hash or exact index with @unique") + require.NoError(t, dg.SetupSchema(`email: string @unique @index(exact) .`)) + + require.NoError(t, dg.DropAll()) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(hash) .`)) + + require.NoError(t, dg.DropAll()) + err = dg.SetupSchema(`mobile: int @unique .`) + require.Error(t, err) + require.ErrorContains(t, err, "index for predicate [mobile] is missing, add int index with @unique") + require.NoError(t, dg.SetupSchema(`mobile: int @unique @index(int) .`)) + + require.NoError(t, dg.DropAll()) + err = dg.SetupSchema(`email: string @unique @index(trigram) .`) + require.Error(t, err) + require.ErrorContains(t, err, "index for predicate [email] is missing,"+ + " add either hash or exact index with @unique") + require.NoError(t, dg.DropAll()) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(trigram,exact) .`)) + + // drop @upsert + require.NoError(t, dg.DropAll()) + err = dg.SetupSchema(`email: string @unique @index(exact) .`) + require.NoError(t, err) + // try to drop @upsert + err = dg.SetupSchema(`email: string @unique @index(exact) .`) + + require.ErrorContains(t, err, "could not drop @upsert from [email]"+ + " predicate when @unique directive specified") + require.NoError(t, dg.SetupSchema(`email: string @unique @upsert @index(exact) .`)) + // drop index + err = dg.SetupSchema(`email: string @unique @upsert .`) + require.Error(t, err) + require.ErrorContains(t, err, "could not drop index [exact] from [email]"+ + " predicate when @unique directive specified") +} + +func TestUniqueTwoMutationSingleBlankNode(t *testing.T) { + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(exact) .`)) + + rdf := `_:a "example@email.com" . ` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + resp, err := dg.Query(emailQuery) + require.NoError(t, err) + require.NoError(t, dgraphtest.CompareJSON(`{ "q": [{"email": "example@email.com"}]}`, string(resp.Json))) + _, err = dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.Error(t, err) + require.ErrorContains(t, err, "could not insert duplicate value [example@email.com] for predicate [email]") +} + +func TestUniqueOneMutationSameValueTwoBlankNode(t *testing.T) { + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(exact) .`)) + + rdf := `_:a "example@email.com" . + _:b "example@email.com" . ` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.Error(t, err) + require.ErrorContains(t, err, "could not insert duplicate value [example@email.com] for predicate [email]") + + resp, err := dg.Query(emailQuery) + require.NoError(t, err) + require.NoError(t, dgraphtest.CompareJSON(`{ "q": [ ]}`, string(resp.Json))) +} + +func TestUniqueOneMutationSameValueSingleBlankNode(t *testing.T) { + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(exact) .`)) + + rdf := `_:a "example@email.com" . + _:a "example@email.com" . ` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + resp, err := dg.Query(emailQuery) + require.NoError(t, err) + require.NoError(t, dgraphtest.CompareJSON(`{ "q": [ { "email": "example@email.com"}]}`, + string(resp.Json))) +} + +func TestUniqueTwoMutattionsTwoHardCodedUIDs(t *testing.T) { + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(exact) .`)) + + rdf := `<0x5> "example@email.com" . ` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + + resp, err := dg.Query(emailQueryWithUid) + require.NoError(t, err) + require.NoError(t, dgraphtest.CompareJSON(`{ "q": [ {"email": "example@email.com","uid" :"0x5"}]}`, + string(resp.Json))) + + rdf = `<0x6> "example@email.com" . ` + _, err = dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.Error(t, err) + require.ErrorContains(t, err, "could not insert duplicate value [example@email.com] for predicate [email]") +} + +func TestUniqueHardCodedUidsWithDiffrentNotation(t *testing.T) { + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(exact) .`)) + + rdf := `<0xad> "example@email.com" . ` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + + resp, err := dg.Query(emailQueryWithUid) + require.NoError(t, err) + require.NoError(t, dgraphtest.CompareJSON(`{ "q": [ {"email": "example@email.com","uid" :"0xad"}]}`, + string(resp.Json))) + + rdf = `<0o255> "example@email.com" . ` + _, err = dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + resp, err = dg.Query(emailQueryWithUid) + require.NoError(t, err) + require.NoError(t, dgraphtest.CompareJSON(`{ "q": [ {"email": "example@email.com","uid" :"0xad"}]}`, + string(resp.Json))) + + rdf = `<0b10101101> "example@email.com" . ` + _, err = dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + resp, err = dg.Query(emailQueryWithUid) + require.NoError(t, err) + require.NoError(t, dgraphtest.CompareJSON(`{ "q": [ {"email": "example@email.com","uid" :"0xad"}]}`, + string(resp.Json))) + + rdf = `<173> "example@email.com" . ` + _, err = dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + resp, err = dg.Query(emailQueryWithUid) + require.NoError(t, err) + require.NoError(t, dgraphtest.CompareJSON(`{ "q": [ {"email": "example@email.com","uid" :"0xad"}]}`, + string(resp.Json))) + +} + +func TestUniqueSingleMutattionsOneHardCodedUIDSameValue(t *testing.T) { + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(exact) .`)) + + rdf := `<0x5> "example@email.com" . + <0x5> "example@email.com" . ` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + resp, err := dg.Query(emailQueryWithUid) + require.NoError(t, err) + require.NoError(t, dgraphtest.CompareJSON(`{ "q": [ { + "email": "example@email.com", + "uid":"0x5" + }]}`, string(resp.Json))) +} + +func TestUniqueOneMutattionsTwoHardCodedUIDsDiffValue(t *testing.T) { + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(exact) .`)) + + rdf := `<0x5> "example@email.com" . + <0x6> "example@email.com" . ` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.Error(t, err) + require.ErrorContains(t, err, "could not insert duplicate value [example@email.com] for predicate [email]") + + resp, err := dg.Query(emailQuery) + require.NoError(t, err) + require.NoError(t, dgraphtest.CompareJSON(`{ "q": [ ]}`, string(resp.Json))) +} + +func TestUniqueUpsertMutation(t *testing.T) { + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(exact) .`)) + rdf := `_:a "example@email.com" . + _:b "example1@email.com" . ` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + + query := `query{ + v as person(func: eq(email, "example@email.com")) { + email + } + }` + mu := &api.Mutation{ + SetNquads: []byte(`uid(v) "example@email.com" . `), + } + _, err = dg.Upsert(query, mu) + require.NoError(t, err) + resp, err := dg.Query(emailQuery) + require.NoError(t, err) + require.NoError(t, dgraphtest.CompareJSON(`{ "q": [{"email": "example@email.com"} ]}`, string(resp.Json))) + + mu = &api.Mutation{ + SetNquads: []byte(` uid(v) "example1@email.com" .`), + } + _, err = dg.Upsert(query, mu) + require.Error(t, err) + require.ErrorContains(t, err, "could not insert duplicate value [example1@email.com] for predicate [email]") +} + +func TestUniqueWithConditionalUpsertMutation(t *testing.T) { + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(exact) .`)) + rdf := `_:a "example@email.com" . + _:b "example1@email.com" . ` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + resp, err := dg.Query(emailQuery) + require.NoError(t, err) + require.NoError(t, dgraphtest.CompareJSON(`{ "q": [{"email": "example@email.com"} ]}`, string(resp.Json))) + + query := `query{ + v as person(func: eq(email, "example@email.com")) { + email + } + }` + mu := &api.Mutation{ + SetNquads: []byte(`uid(v) "example@email.com" . `), + Cond: "@if(eq(len(v),1))", + } + _, err = dg.Upsert(query, mu) + require.NoError(t, err) + + query = `query{ + v as person(func: eq(email, "example1@email.com")) { + email + } + }` + mu = &api.Mutation{ + SetNquads: []byte(`uid(v) "example@email.com" . `), + Cond: "@if(eq(len(v),1))", + } + _, err = dg.Upsert(query, mu) + require.Error(t, err) + require.ErrorContains(t, err, "could not insert duplicate value [example@email.com] for predicate [email]") +} + +func TestUniqueUpsertMutationWithValOf(t *testing.T) { + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(exact) .`)) + rdf := `_:a "example@email.com" . + _:b "example1@email.com" . ` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + + query := `query{ + v as person(func: eq(email, "example@email.com")) { + email + } + }` + mu := &api.Mutation{ + SetNquads: []byte(`uid(v) "example@email.com" . `), + } + _, err = dg.Upsert(query, mu) + require.NoError(t, err) + + query = `query{ + v as person(func: eq(email, "example@email.com")) { + email + } + var(func: eq(email, "example1@email.com")) { + w as email + } + }` + mu = &api.Mutation{ + SetNquads: []byte(`uid(v) val(w) . `), + } + _, err = dg.Upsert(query, mu) + require.NoError(t, err) + + // test unique using aggregate var + query = `query{ + v as person(func: eq(email, "example@email.com")) { + email + } + var(func: eq(email, "example1@email.com")) { + emails as email + } + me() { + d as min(val(emails)) + } + }` + mu = &api.Mutation{ + SetNquads: []byte(` uid(v) val(d) . `), + } + + _, err = dg.Upsert(query, mu) + require.Error(t, err) + require.ErrorContains(t, err, "could not insert duplicate value [example1@email.com] for predicate [email]") + + query = `query{ + var(func: eq(email, "example1@email.com")) { + emails as email + } + me() { + d as min(val(emails)) + } + }` + mu = &api.Mutation{ + SetNquads: []byte(`<0x100> val(d) . `), + } + _, err = dg.Upsert(query, mu) + require.Error(t, err) + require.ErrorContains(t, err, "could not insert duplicate value [example1@email.com] for predicate [email]") + + query = `query{ + var(func: eq(email, "example1@email.com")) { + emails as email + } + me() { + d as min(val(emails)) + } + }` + mu = &api.Mutation{ + SetNquads: []byte(`_:a val(d) . `), + } + _, err = dg.Upsert(query, mu) + require.Error(t, err) + require.ErrorContains(t, err, "could not insert duplicate value [example1@email.com] for predicate [email]") +} + +func TestUniqueUpsertSingleMutationTwoBlankNode(t *testing.T) { + schema := `email: string @unique @index(exact) . + fullName :string @index(exact) .` + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(schema)) + rdf := `_:a "person1@email.com" . + _:a "person2@email.com" . + _:b "person2@email.com" . + _:b "person1@email.com" .` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + + query := `query{ + v as person(func: eq(fullName, "person1@email.com")) { + w as fullName + } + }` + mu := &api.Mutation{ + SetNquads: []byte(`uid(v) val(w) . `), + } + _, err = dg.Upsert(query, mu) + require.Error(t, err) + require.ErrorContains(t, err, "could not insert duplicate value [person1@email.com] for predicate [email]") + + query = `query{ + v as person(func: eq(fullName, "person1@email.com")) { + w as email + } + }` + mu = &api.Mutation{ + SetNquads: []byte(`uid(v) val(w) . `), + } + _, err = dg.Upsert(query, mu) + require.NoError(t, err) +} + +func TestUniqueForInt(t *testing.T) { + schema := `mobile: int @unique @index(int) .` + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(schema)) + rdf := `_:a "1234567890" . ` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + _, err = dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.Error(t, err) + require.ErrorContains(t, err, "could not insert duplicate value [1234567890] for predicate [mobile]") + query := `{ + q(func: eq(mobile, 1234567890)) { + mobile + } + }` + resp, err := dg.Query(query) + require.NoError(t, err) + require.NoError(t, dgraphtest.CompareJSON(`{ "q": [ { "mobile": 1234567890}]}`, string(resp.Json))) +} + +func TestUniqueForLangDirective(t *testing.T) { + schema := `name: string @unique @lang @index(exact) . + email: string .` + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(schema)) + rdf := `_:a "अमित" . ` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + _, err = dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.Error(t, err) + require.ErrorContains(t, err, "could not insert duplicate value [अमित] for predicate [name]") + _, err = dg.Mutate(&api.Mutation{ + SetNquads: []byte(`_:a "अमित" .`), + CommitNow: true, + }) + require.NoError(t, err) +} + +func TestUniqueTwoWaySwapMutation(t *testing.T) { + schema := `email: string @unique @index(exact) .` + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(schema)) + rdf := `<0x22> "aman@dgraph.io" . + <0x33> "shiva@dgraph.io" . ` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + rdf = `<0x33> "aman@dgraph.io" . + <0x22> "shiva@dgraph.io" .` + _, err = dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + query := `query{ + var(func: eq(email, "aman@dgraph.io")) { + emails as email + } + me() { + d as min(val(emails)) + } + }` + mu := &api.Mutation{ + SetNquads: []byte(` <0x10> val(d) . + <0x33> "harshil@dgraph.io" .`), + } + + _, err = dg.Upsert(query, mu) + require.NoError(t, err) +} + +func TestUnqueFourWaySwapMutation(t *testing.T) { + schema := `email: string @unique @index(exact) .` + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(schema)) + rdf := `<0x22> "aman@dgraph.io" . + <0x33> "shiva@dgraph.io" . + <0x44> "jassi@dgraph.io" . + <0x55> "siddesh@dgraph.io" .` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + rdf = `<0x33> "aman@dgraph.io" . + <0x22> "shiva@dgraph.io" . + <0x55> "jassi@dgraph.io" . + <0x44> "siddesh@dgraph.io" .` + _, err = dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + rdf = `<0x44> "aman@dgraph.io" . + <0x55> "shiva@dgraph.io" . + <0x22> "jassi@dgraph.io" . + <0x33> "siddesh@dgraph.io" .` + _, err = dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + rdf = `<0x55> "aman@dgraph.io" . + <0x44> "shiva@dgraph.io" . + <0x33> "jassi@dgraph.io" . + <0x22> "siddesh@dgraph.io" .` + _, err = dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) +} + +func TestUniqueDeleteMutation(t *testing.T) { + schema := `email: string @unique @index(exact) .` + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(schema)) + rdf := `<0x22> "example1@gmail.com" . + <0x33> "example2@gmail.com" .` + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(rdf), + CommitNow: true, + }) + require.NoError(t, err) + query := `query{ + u as var(func: eq(email, "example1@gmail.com")) + }` + mu := &api.Mutation{ + SetNquads: []byte(`<0x100> "example1@gmail.com" . `), + DelNquads: []byte(`uid(u) "example1@gmail.com" .`), + } + _, err = dg.Upsert(query, mu) + require.Error(t, err) + require.ErrorContains(t, err, "could not insert duplicate value [example1@gmail.com]"+ + " for predicate [email]") +} + +func TestConcurrencyMutationsDiffrentValuesForDiffrentBlankNode(t *testing.T) { + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(exact) .`)) + concurrency := 1000 + wg := &sync.WaitGroup{} + for i := 0; i < concurrency; i++ { + wg.Add(1) + go func(i int) { + defer wg.Done() + _, _ = dg.Mutate(&api.Mutation{ + SetNquads: []byte(fmt.Sprintf(`_:a "example%v@email.com" .`, i)), + CommitNow: true, + }) + }(i) + } + wg.Wait() + query := `{ + allMails(func: has(email)) { + count(uid) + } + }` + resp, err := dg.Query(query) + require.NoError(t, err) + // there should be 1000 emails in DB. + require.NoError(t, dgraphtest.CompareJSON(`{"allMails":[{"count":1000}]}`, string(resp.Json))) +} + +func TestUniqueTwoTxnWithoutCommit(t *testing.T) { + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(exact) .`)) + ctx := context.Background() + rdf := `_:a "example@email.com" . ` + txn1 := dg.NewTxn() + _, err := txn1.Mutate(ctx, &api.Mutation{ + SetNquads: []byte(rdf), + }) + require.NoError(t, err) + + txn2 := dg.NewTxn() + _, err = txn2.Mutate(ctx, &api.Mutation{ + SetNquads: []byte(rdf), + }) + require.NoError(t, err) + + require.NoError(t, txn1.Commit(ctx)) + require.Error(t, txn2.Commit(ctx)) + resp, err := dg.Query(emailQuery) + require.NoError(t, err) + // there should be only one email data as expected. + require.NoError(t, dgraphtest.CompareJSON(`{"q":[{"email":"example@email.com"}]}`, string(resp.Json))) +} + +func TestUniqueSingelTxnDuplicteValuesWithoutCommit(t *testing.T) { + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(`email: string @unique @index(exact) .`)) + ctx := context.Background() + rdf := `_:a "example@email.com" . ` + txn1 := dg.NewTxn() + _, err := txn1.Mutate(ctx, &api.Mutation{ + SetNquads: []byte(rdf), + }) + require.NoError(t, err) + _, err = txn1.Mutate(ctx, &api.Mutation{ + SetNquads: []byte(rdf), + }) + require.Error(t, err) + require.ErrorContains(t, err, "could not insert duplicate value [example@email.com] for predicate [email]") + + err = txn1.Commit(ctx) + require.Error(t, err) + require.ErrorContains(t, err, "Transaction has already been committed or discarded") +} + +func TestConcurrency2(t *testing.T) { + dg := setUpDgraph(t) + require.NoError(t, dg.SetupSchema(`email: string @unique @upsert @index(exact) .`)) + concurrency := 100 + rand.Seed(time.Now().UnixNano()) + errChan := make(chan error) + wg := &sync.WaitGroup{} + for i := 0; i < concurrency; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for j := 1; j < concurrency; j++ { + rN := rand.Intn(concurrency) + _, err := dg.Mutate(&api.Mutation{ + SetNquads: []byte(fmt.Sprintf(`_:%v "example%v@email.com" .`, rN, rN)), + CommitNow: true, + }) + if err != nil { + errChan <- err + } + } + }() + } + + go func() { + wg.Wait() + close(errChan) + }() + + for err := range errChan { + if !(strings.Contains(err.Error(), "Transaction has been aborted. Please retry")) && + !(strings.Contains(err.Error(), "could not insert duplicate value")) { + t.Fatal(err.Error()) + } + + } + + for i := 0; i < concurrency; i++ { + emailQuery := fmt.Sprintf(`{ + q(func: eq(email, "example%v@email.com")) { + email + } + }`, i) + resp, err := dg.Query(emailQuery) + require.NoError(t, err) + err1 := dgraphtest.CompareJSON(fmt.Sprintf(`{"q":[{"email":"example%v@email.com"}]}`, i), string(resp.Json)) + err2 := dgraphtest.CompareJSON(fmt.Sprintf(`{ "q": [ ]}`), string(resp.Json)) + if err1 != nil && err2 != nil { + t.Fatal() + } + } +} diff --git a/worker/mutation.go b/worker/mutation.go index cb6568cb586..25cdfb9da46 100644 --- a/worker/mutation.go +++ b/worker/mutation.go @@ -419,11 +419,19 @@ func checkSchema(s *pb.SchemaUpdate) error { } // If schema update has upsert directive, it should have index directive. - if s.Upsert && len(s.Tokenizer) == 0 { + if s.Upsert && len(s.Tokenizer) == 0 && !s.Unique { return errors.Errorf("Index tokenizer is mandatory for: [%s] when specifying @upsert directive", x.ParseAttr(s.Predicate)) } + if s.Unique { + ctx := context.WithValue(context.Background(), schema.IsWrite, false) + prevSchema, _ := schema.State().Get(ctx, s.Predicate) + if err := validateSchemaForUnique(prevSchema, s); err != nil { + return err + } + } + t, err := schema.State().TypeOf(s.Predicate) if err != nil { // No schema previously defined, so no need to do checks about schema conversions. @@ -457,6 +465,52 @@ func checkSchema(s *pb.SchemaUpdate) error { return nil } +func validateSchemaForUnique(prevSchema pb.SchemaUpdate, currentSchema *pb.SchemaUpdate) error { + validTokenizer := func(tokenizers []string) bool { + for _, value := range tokenizers { + if value == "hash" || value == "exact" || value == "int" { + return true + } + } + return false + } + if prevSchema.Predicate != "" { + if prevSchema.Upsert && !currentSchema.Upsert { + return errors.Errorf("could not drop @upsert from [%v] predicate when @unique directive specified", + x.ParseAttr(currentSchema.Predicate)) + } + + if prevSchema.Unique && !validTokenizer(currentSchema.Tokenizer) { + return errors.Errorf("could not drop index %v from [%v] predicate when @unique directive specified", + prevSchema.Tokenizer, x.ParseAttr(currentSchema.Predicate)) + } + } + if !currentSchema.Upsert { + currentSchema.Upsert = true + } + switch currentSchema.ValueType { + case pb.Posting_STRING: + if len(currentSchema.Tokenizer) == 0 || + (len(currentSchema.Tokenizer) > 0 && !validTokenizer(currentSchema.Tokenizer)) { + + return errors.Errorf("index for predicate [%v] is missing, add either hash or exact index with @unique", + x.ParseAttr(currentSchema.Predicate)) + } else { + return nil + } + + case pb.Posting_INT: + if len(currentSchema.Tokenizer) == 0 { + return errors.Errorf("index for predicate [%v] is missing, add int index with @unique", + x.ParseAttr(currentSchema.Predicate)) + } else { + return nil + } + } + + return errors.Errorf("@unique directive not supported on [%v] type predicate", currentSchema.ValueType.String()) +} + // ValidateAndConvert checks compatibility or converts to the schema type if the storage type is // specified. If no storage type is specified then it converts to the schema type. func ValidateAndConvert(edge *pb.DirectedEdge, su *pb.SchemaUpdate) error { diff --git a/worker/schema.go b/worker/schema.go index cbef569770a..d533b794704 100644 --- a/worker/schema.go +++ b/worker/schema.go @@ -56,7 +56,7 @@ func getSchema(ctx context.Context, s *pb.SchemaRequest) (*pb.SchemaResult, erro if len(s.Fields) > 0 { fields = s.Fields } else { - fields = []string{"type", "index", "tokenizer", "reverse", "count", "list", "upsert", + fields = []string{"type", "index", "tokenizer", "reverse", "count", "list", "upsert", "unique", "lang", "noconflict"} } @@ -110,6 +110,8 @@ func populateSchema(attr string, fields []string) *pb.SchemaNode { schemaNode.List = pred.GetList() case "upsert": schemaNode.Upsert = pred.GetUpsert() + case "unique": + schemaNode.Unique = pred.GetUnique() case "lang": schemaNode.Lang = pred.GetLang() case "noconflict":