diff --git a/edgraph/server.go b/edgraph/server.go index e74ddf30817..e35394887f4 100644 --- a/edgraph/server.go +++ b/edgraph/server.go @@ -40,6 +40,7 @@ import ( "github.com/dgraph-io/dgraph/protos/pb" "github.com/dgraph-io/dgraph/query" "github.com/dgraph-io/dgraph/schema" + "github.com/dgraph-io/dgraph/types" "github.com/dgraph-io/dgraph/types/facets" "github.com/dgraph-io/dgraph/worker" "github.com/dgraph-io/dgraph/x" @@ -365,6 +366,7 @@ func (s *Server) Alter(ctx context.Context, op *api.Operation) (*api.Payload, er glog.Infof("Got schema: %+v\n", result.Schemas) // TODO: Maybe add some checks about the schema. m.Schema = result.Schemas + m.Types = result.Types _, err = query.ApplyMutations(ctx, m) return empty, err } @@ -595,18 +597,27 @@ func (s *Server) doQuery(ctx context.Context, req *api.Request) (resp *api.Respo } // Core processing happens here. - var er query.ExecuteResult + var er query.ExecutionResult if er, err = queryRequest.Process(ctx); err != nil { return resp, x.Wrap(err) } - resp.Schema = er.SchemaNode - var js []byte - if len(resp.Schema) > 0 { - sort.Slice(resp.Schema, func(i, j int) bool { - return resp.Schema[i].Predicate < resp.Schema[j].Predicate + if len(er.SchemaNode) > 0 || len(er.Types) > 0 { + sort.Slice(er.SchemaNode, func(i, j int) bool { + return er.SchemaNode[i].Predicate < er.SchemaNode[j].Predicate + }) + sort.Slice(er.Types, func(i, j int) bool { + return er.Types[i].TypeName < er.Types[j].TypeName }) - js, err = json.Marshal(map[string]interface{}{"schema": resp.Schema}) + + respMap := make(map[string]interface{}) + if len(er.SchemaNode) > 0 { + respMap["schema"] = er.SchemaNode + } + if len(er.Types) > 0 { + respMap["types"] = formatTypes(er.Types) + } + js, err = json.Marshal(respMap) } else { js, err = query.ToJson(&l, er.Subgraphs) } @@ -871,3 +882,53 @@ func validatePredName(name string) error { } return nil } + +// formatField takes a SchemaUpdate representing a field in a type and converts +// it into a map containing keys for the type name and the type. +func formatField(field *pb.SchemaUpdate) map[string]string { + fieldMap := make(map[string]string) + fieldMap["name"] = field.Predicate + typ := "" + if field.List { + typ += "[" + } + + if field.ValueType == pb.Posting_OBJECT { + typ += field.ObjectTypeName + } else { + typeId := types.TypeID(field.ValueType) + typ += typeId.Name() + } + + if field.NonNullable { + typ += "!" + } + if field.List { + typ += "]" + } + if field.NonNullableList { + typ += "!" + } + fieldMap["type"] = typ + + return fieldMap +} + +// formatTypes takes a list of TypeUpdates and converts them in to a list of +// maps in a format that is human-readable to be marshaled into JSON. +func formatTypes(types []*pb.TypeUpdate) []map[string]interface{} { + var res []map[string]interface{} + for _, typ := range types { + typeMap := make(map[string]interface{}) + typeMap["name"] = typ.TypeName + typeMap["fields"] = make([]map[string]string, 0) + + for _, field := range typ.Fields { + fieldMap := formatField(field) + typeMap["fields"] = append(typeMap["fields"].([]map[string]string), fieldMap) + } + + res = append(res, typeMap) + } + return res +} diff --git a/gql/parser.go b/gql/parser.go index 4670979e84c..f7c63d498d7 100644 --- a/gql/parser.go +++ b/gql/parser.go @@ -884,14 +884,19 @@ func parseListItemNames(it *lex.ItemIterator) ([]string, error) { return items, it.Errorf("Expecting ] to end list but none was found") } -// parses till rightround is found -func parseSchemaPredicates(it *lex.ItemIterator, s *pb.SchemaRequest) error { - // pred should be followed by colon +// parseSchemaPredsOrTypes parses till rightround is found +func parseSchemaPredsOrTypes(it *lex.ItemIterator, s *pb.SchemaRequest) error { + // pred or type should be followed by colon it.Next() item := it.Item() - if item.Typ != itemName && item.Val != "pred" { + if item.Typ != itemName && !(item.Val == "pred" || item.Val == "type") { return item.Errorf("Invalid schema block") } + parseTypes := false + if item.Val == "type" { + parseTypes = true + } + it.Next() item = it.Item() if item.Typ != itemColon { @@ -902,12 +907,22 @@ func parseSchemaPredicates(it *lex.ItemIterator, s *pb.SchemaRequest) error { it.Next() item = it.Item() if item.Typ == itemName { - s.Predicates = append(s.Predicates, item.Val) + if parseTypes { + s.Types = append(s.Types, item.Val) + } else { + s.Predicates = append(s.Predicates, item.Val) + } } else if item.Typ == itemLeftSquare { - var err error - if s.Predicates, err = parseListItemNames(it); err != nil { + names, err := parseListItemNames(it) + if err != nil { return err } + + if parseTypes { + s.Types = names + } else { + s.Predicates = names + } } else { return item.Errorf("Invalid schema block") } @@ -952,7 +967,7 @@ func getSchema(it *lex.ItemIterator) (*pb.SchemaRequest, error) { return nil, item.Errorf("Too many left rounds in schema block") } leftRoundSeen = true - if err := parseSchemaPredicates(it, &s); err != nil { + if err := parseSchemaPredsOrTypes(it, &s); err != nil { return nil, err } default: diff --git a/gql/parser_test.go b/gql/parser_test.go index d4bc77becd2..97ed3d9816a 100644 --- a/gql/parser_test.go +++ b/gql/parser_test.go @@ -1572,6 +1572,33 @@ func TestParseSchemaAndQuery(t *testing.T) { require.Contains(t, err.Error(), "Schema block is not allowed with query block") } +func TestParseSchemaType(t *testing.T) { + query := ` + schema (type: Person) { + } + ` + res, err := Parse(Request{Str: query}) + require.NoError(t, err) + require.Equal(t, len(res.Schema.Predicates), 0) + require.Equal(t, len(res.Schema.Types), 1) + require.Equal(t, res.Schema.Types[0], "Person") + require.Equal(t, len(res.Schema.Fields), 0) +} + +func TestParseSchemaTypeMulti(t *testing.T) { + query := ` + schema (type: [Person, Animal]) { + } + ` + res, err := Parse(Request{Str: query}) + require.NoError(t, err) + require.Equal(t, len(res.Schema.Predicates), 0) + require.Equal(t, len(res.Schema.Types), 2) + require.Equal(t, res.Schema.Types[0], "Person") + require.Equal(t, res.Schema.Types[1], "Animal") + require.Equal(t, len(res.Schema.Fields), 0) +} + func TestParseSchemaError(t *testing.T) { query := ` schema () { diff --git a/protos/pb.proto b/protos/pb.proto index d74a6ca8555..98609a5c143 100644 --- a/protos/pb.proto +++ b/protos/pb.proto @@ -199,6 +199,7 @@ message Mutations { repeated SchemaUpdate schema = 4; bool drop_all = 5; bool ignore_index_conflict = 6; + repeated TypeUpdate types = 7; } message Snapshot { @@ -316,6 +317,8 @@ message SchemaRequest { repeated string predicates = 2; // fields can be on of type, index, reverse or tokenizer repeated string fields = 3; + + repeated string types = 4; } message SchemaResult { diff --git a/protos/pb/pb.pb.go b/protos/pb/pb.pb.go index 96d5104a3a4..d93bafb0b34 100644 --- a/protos/pb/pb.pb.go +++ b/protos/pb/pb.pb.go @@ -1551,6 +1551,7 @@ type Mutations struct { Schema []*SchemaUpdate `protobuf:"bytes,4,rep,name=schema,proto3" json:"schema,omitempty"` DropAll bool `protobuf:"varint,5,opt,name=drop_all,json=dropAll,proto3" json:"drop_all,omitempty"` IgnoreIndexConflict bool `protobuf:"varint,6,opt,name=ignore_index_conflict,json=ignoreIndexConflict,proto3" json:"ignore_index_conflict,omitempty"` + Types []*TypeUpdate `protobuf:"bytes,7,rep,name=types,proto3" json:"types,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1631,6 +1632,13 @@ func (m *Mutations) GetIgnoreIndexConflict() bool { return false } +func (m *Mutations) GetTypes() []*TypeUpdate { + if m != nil { + return m.Types + } + return nil +} + type Snapshot struct { Context *RaftContext `protobuf:"bytes,1,opt,name=context,proto3" json:"context,omitempty"` Index uint64 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` @@ -2496,6 +2504,7 @@ type SchemaRequest struct { Predicates []string `protobuf:"bytes,2,rep,name=predicates,proto3" json:"predicates,omitempty"` // fields can be on of type, index, reverse or tokenizer Fields []string `protobuf:"bytes,3,rep,name=fields,proto3" json:"fields,omitempty"` + Types []string `protobuf:"bytes,4,rep,name=types,proto3" json:"types,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -2555,6 +2564,13 @@ func (m *SchemaRequest) GetFields() []string { return nil } +func (m *SchemaRequest) GetTypes() []string { + if m != nil { + return m.Types + } + return nil +} + type SchemaResult struct { Schema []*api.SchemaNode `protobuf:"bytes,1,rep,name=schema,proto3" json:"schema,omitempty"` // Deprecated: Do not use. XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -3621,214 +3637,216 @@ func init() { func init() { proto.RegisterFile("pb.proto", fileDescriptor_f80abaa17e25ccc8) } var fileDescriptor_f80abaa17e25ccc8 = []byte{ - // 3307 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x59, 0x4b, 0x73, 0x1b, 0x49, - 0x72, 0x66, 0x37, 0x80, 0x46, 0x77, 0x02, 0xa4, 0xb0, 0x25, 0xad, 0x06, 0x43, 0xed, 0x52, 0x9c, - 0x1e, 0x69, 0x44, 0x49, 0x23, 0x4a, 0xc3, 0x19, 0xdb, 0xab, 0x75, 0xf8, 0xc0, 0x07, 0x24, 0x73, - 0x86, 0x2f, 0x17, 0x40, 0xad, 0x3d, 0xe1, 0x30, 0xa2, 0xd0, 0x5d, 0x04, 0x7b, 0xd9, 0xe8, 0x6e, - 0x77, 0x35, 0x18, 0xa0, 0x6e, 0x3e, 0xd8, 0xbf, 0x61, 0x0f, 0x0e, 0xdf, 0x7c, 0xf1, 0xc5, 0xd7, - 0x39, 0xfa, 0xe2, 0x08, 0x1f, 0x1d, 0xfe, 0x05, 0x0e, 0xd9, 0xff, 0xc0, 0x11, 0x8e, 0xf0, 0xcd, - 0x51, 0x59, 0xd5, 0x0f, 0x40, 0xa4, 0x34, 0xe3, 0x08, 0x9f, 0xd0, 0xf9, 0xa8, 0xd7, 0x57, 0x99, - 0x59, 0x99, 0x09, 0xb0, 0x93, 0xd1, 0x66, 0x92, 0xc6, 0x59, 0x4c, 0xcc, 0x64, 0xb4, 0xea, 0xb0, - 0x24, 0x50, 0xe4, 0xea, 0xa3, 0x71, 0x90, 0x9d, 0x4f, 0x47, 0x9b, 0x5e, 0x3c, 0x79, 0xee, 0x8f, - 0x53, 0x96, 0x9c, 0x3f, 0x0b, 0xe2, 0xe7, 0x23, 0xe6, 0x8f, 0x79, 0xfa, 0x3c, 0x19, 0x3d, 0xcf, - 0xc7, 0xb9, 0xab, 0x50, 0x3f, 0x08, 0x44, 0x46, 0x08, 0xd4, 0xa7, 0x81, 0x2f, 0xba, 0xc6, 0x7a, - 0x6d, 0xc3, 0xa2, 0xf8, 0xed, 0x1e, 0x82, 0x33, 0x60, 0xe2, 0xe2, 0x0d, 0x0b, 0xa7, 0x9c, 0x74, - 0xa0, 0x76, 0xc9, 0xc2, 0xae, 0xb1, 0x6e, 0x6c, 0xb4, 0xa9, 0xfc, 0x24, 0x9b, 0x60, 0x5f, 0xb2, - 0x70, 0x98, 0x5d, 0x25, 0xbc, 0x6b, 0xae, 0x1b, 0x1b, 0x2b, 0x5b, 0xb7, 0x37, 0x93, 0xd1, 0xe6, - 0x49, 0x2c, 0xb2, 0x20, 0x1a, 0x6f, 0xbe, 0x61, 0xe1, 0xe0, 0x2a, 0xe1, 0xb4, 0x79, 0xa9, 0x3e, - 0xdc, 0x63, 0x68, 0xf5, 0x53, 0xef, 0xd5, 0x34, 0xf2, 0xb2, 0x20, 0x8e, 0xe4, 0x8a, 0x11, 0x9b, - 0x70, 0x9c, 0xd1, 0xa1, 0xf8, 0x2d, 0x79, 0x2c, 0x1d, 0x8b, 0x6e, 0x6d, 0xbd, 0x26, 0x79, 0xf2, - 0x9b, 0x74, 0xa1, 0x19, 0x88, 0xdd, 0x78, 0x1a, 0x65, 0xdd, 0xfa, 0xba, 0xb1, 0x61, 0xd3, 0x9c, - 0x74, 0xff, 0xcb, 0x84, 0xc6, 0x9f, 0x4c, 0x79, 0x7a, 0x85, 0xe3, 0xb2, 0x2c, 0xcd, 0xe7, 0x92, - 0xdf, 0xe4, 0x0e, 0x34, 0x42, 0x16, 0x8d, 0x45, 0xd7, 0xc4, 0xc9, 0x14, 0x41, 0xee, 0x81, 0xc3, - 0xce, 0x32, 0x9e, 0x0e, 0xa7, 0x81, 0xdf, 0xad, 0xad, 0x1b, 0x1b, 0x16, 0xb5, 0x91, 0x71, 0x1a, - 0xf8, 0xe4, 0x53, 0xb0, 0xfd, 0x78, 0xe8, 0x55, 0xd7, 0xf2, 0x63, 0x5c, 0x8b, 0x7c, 0x0e, 0xf6, - 0x34, 0xf0, 0x87, 0x61, 0x20, 0xb2, 0x6e, 0x63, 0xdd, 0xd8, 0x68, 0x6d, 0xd9, 0xf2, 0xb0, 0x12, - 0x3b, 0xda, 0x9c, 0x06, 0x3e, 0x82, 0xf8, 0x04, 0x6c, 0x91, 0x7a, 0xc3, 0xb3, 0x69, 0xe4, 0x75, - 0x2d, 0x54, 0xba, 0x25, 0x95, 0x2a, 0xa7, 0xa6, 0x4d, 0xa1, 0x08, 0x79, 0xac, 0x94, 0x5f, 0xf2, - 0x54, 0xf0, 0x6e, 0x53, 0x2d, 0xa5, 0x49, 0xf2, 0x02, 0x5a, 0x67, 0xcc, 0xe3, 0xd9, 0x30, 0x61, - 0x29, 0x9b, 0x74, 0xed, 0x72, 0xa2, 0x57, 0x92, 0x7d, 0x22, 0xb9, 0x82, 0xc2, 0x59, 0x41, 0x90, - 0xaf, 0x61, 0x19, 0x29, 0x31, 0x3c, 0x0b, 0xc2, 0x8c, 0xa7, 0x5d, 0x07, 0xc7, 0xac, 0xe0, 0x18, - 0xe4, 0x0c, 0x52, 0xce, 0x69, 0x5b, 0x29, 0x29, 0x0e, 0xf9, 0x25, 0x00, 0x9f, 0x25, 0x2c, 0xf2, - 0x87, 0x2c, 0x0c, 0xbb, 0x80, 0x7b, 0x70, 0x14, 0x67, 0x3b, 0x0c, 0xc9, 0x27, 0x72, 0x7f, 0xcc, - 0x1f, 0x66, 0xa2, 0xbb, 0xbc, 0x6e, 0x6c, 0xd4, 0xa9, 0x25, 0xc9, 0x81, 0x70, 0xb7, 0xc0, 0x41, - 0x8b, 0xc0, 0x13, 0x3f, 0x04, 0xeb, 0x52, 0x12, 0xca, 0x70, 0x5a, 0x5b, 0xcb, 0x72, 0xc9, 0xc2, - 0x68, 0xa8, 0x16, 0xba, 0x6b, 0x60, 0x1f, 0xb0, 0x68, 0x9c, 0x5b, 0x9a, 0xbc, 0x0a, 0x1c, 0xe0, - 0x50, 0xfc, 0x76, 0x7f, 0x67, 0x82, 0x45, 0xb9, 0x98, 0x86, 0x19, 0x79, 0x04, 0x20, 0x81, 0x9e, - 0xb0, 0x2c, 0x0d, 0x66, 0x7a, 0xd6, 0x12, 0x6a, 0x67, 0x1a, 0xf8, 0x87, 0x28, 0x22, 0x2f, 0xa0, - 0x8d, 0xb3, 0xe7, 0xaa, 0x66, 0xb9, 0x81, 0x62, 0x7f, 0xb4, 0x85, 0x2a, 0x7a, 0xc4, 0x5d, 0xb0, - 0xf0, 0x6e, 0x95, 0x7d, 0x2d, 0x53, 0x4d, 0x91, 0x87, 0xb0, 0x12, 0x44, 0x99, 0xc4, 0xde, 0xcb, - 0x86, 0x3e, 0x17, 0xf9, 0xe5, 0x2f, 0x17, 0xdc, 0x3d, 0x2e, 0x32, 0xf2, 0x15, 0x28, 0x00, 0xf3, - 0x05, 0x1b, 0xb8, 0xe0, 0x4a, 0x71, 0x31, 0x42, 0xad, 0x88, 0x3a, 0x7a, 0xc5, 0x67, 0xd0, 0x92, - 0xe7, 0xcb, 0x47, 0x58, 0x38, 0xa2, 0x8d, 0xa7, 0xd1, 0x70, 0x50, 0x90, 0x0a, 0x5a, 0x5d, 0x42, - 0x23, 0x0d, 0x4c, 0x19, 0x04, 0x7e, 0xbb, 0x3d, 0x68, 0x1c, 0xa7, 0x3e, 0x4f, 0xaf, 0xb5, 0x71, - 0x02, 0x75, 0x9f, 0x0b, 0x0f, 0xdd, 0xcf, 0xa6, 0xf8, 0x5d, 0xda, 0x7d, 0xad, 0x62, 0xf7, 0xee, - 0xdf, 0x19, 0xd0, 0xea, 0xc7, 0x69, 0x76, 0xc8, 0x85, 0x60, 0x63, 0x4e, 0xee, 0x43, 0x23, 0x96, - 0xd3, 0x6a, 0x84, 0x1d, 0xb9, 0x27, 0x5c, 0x87, 0x2a, 0xfe, 0xc2, 0x3d, 0x98, 0x37, 0xdf, 0xc3, - 0x1d, 0x68, 0x28, 0x8f, 0x91, 0xde, 0xd4, 0xa0, 0x8a, 0x90, 0x58, 0xc7, 0x67, 0x67, 0x82, 0x2b, - 0x2c, 0x1b, 0x54, 0x53, 0x37, 0x9b, 0xd5, 0xef, 0x01, 0xc8, 0xfd, 0xfd, 0x44, 0x2b, 0x70, 0xcf, - 0xa1, 0x45, 0xd9, 0x59, 0xb6, 0x1b, 0x47, 0x19, 0x9f, 0x65, 0x64, 0x05, 0xcc, 0xc0, 0x47, 0x88, - 0x2c, 0x6a, 0x06, 0xbe, 0xdc, 0xdc, 0x38, 0x8d, 0xa7, 0x09, 0x22, 0xb4, 0x4c, 0x15, 0x81, 0x50, - 0xfa, 0x7e, 0x8a, 0x3b, 0x96, 0x50, 0xfa, 0x7e, 0x4a, 0xee, 0x43, 0x4b, 0x44, 0x2c, 0x11, 0xe7, - 0x71, 0x26, 0x37, 0x57, 0xc7, 0xcd, 0x41, 0xce, 0x1a, 0x08, 0xf7, 0x9f, 0x0d, 0xb0, 0x0e, 0xf9, - 0x64, 0xc4, 0xd3, 0xf7, 0x56, 0xf9, 0x14, 0x6c, 0x9c, 0x78, 0x18, 0xf8, 0x7a, 0xa1, 0x26, 0xd2, - 0xfb, 0xfe, 0xb5, 0x4b, 0xdd, 0x05, 0x2b, 0xe4, 0x4c, 0x82, 0xaf, 0xec, 0x4c, 0x53, 0x12, 0x1b, - 0x36, 0x19, 0xfa, 0x9c, 0xf9, 0x18, 0x62, 0x6c, 0x6a, 0xb1, 0xc9, 0x1e, 0x67, 0xbe, 0xdc, 0x5b, - 0xc8, 0x44, 0x36, 0x9c, 0x26, 0x3e, 0xcb, 0x38, 0x86, 0x96, 0xba, 0x34, 0x1c, 0x91, 0x9d, 0x22, - 0x87, 0x3c, 0x81, 0x9f, 0x79, 0xe1, 0x54, 0xc8, 0xb8, 0x16, 0x44, 0x67, 0xf1, 0x30, 0x8e, 0xc2, - 0x2b, 0xc4, 0xd7, 0xa6, 0xb7, 0xb4, 0x60, 0x3f, 0x3a, 0x8b, 0x8f, 0xa3, 0xf0, 0xca, 0xfd, 0xc1, - 0x84, 0xc6, 0x6b, 0x84, 0xe1, 0x05, 0x34, 0x27, 0x78, 0xa0, 0xdc, 0x7b, 0xef, 0x4a, 0x84, 0x51, - 0xb6, 0xa9, 0x4e, 0x2a, 0x7a, 0x51, 0x96, 0x5e, 0xd1, 0x5c, 0x4d, 0x8e, 0xc8, 0xd8, 0x28, 0xe4, - 0x99, 0xd0, 0x16, 0x51, 0x19, 0x31, 0x50, 0x02, 0x3d, 0x42, 0xab, 0x2d, 0xc2, 0x5a, 0x5b, 0x84, - 0x95, 0xac, 0x82, 0xed, 0x9d, 0x73, 0xef, 0x42, 0x4c, 0x27, 0x1a, 0xf4, 0x82, 0x5e, 0x7d, 0x05, - 0xed, 0xea, 0x3e, 0xe4, 0x1b, 0x74, 0xc1, 0xaf, 0x10, 0xf8, 0x3a, 0x95, 0x9f, 0x64, 0x1d, 0x1a, - 0xe8, 0xe1, 0x08, 0x7b, 0x6b, 0x0b, 0xe4, 0x76, 0xd4, 0x10, 0xaa, 0x04, 0xbf, 0x36, 0x7f, 0x65, - 0xc8, 0x79, 0xaa, 0xbb, 0xab, 0xce, 0xe3, 0xdc, 0x3c, 0x8f, 0x1a, 0x52, 0x99, 0xc7, 0xfd, 0x1f, - 0x13, 0xda, 0xdf, 0xf3, 0x34, 0x3e, 0x49, 0xe3, 0x24, 0x16, 0x2c, 0x24, 0xdb, 0xf3, 0xa7, 0x53, - 0x28, 0xae, 0xcb, 0xc1, 0x55, 0xb5, 0xcd, 0x7e, 0x71, 0x5c, 0x85, 0x4e, 0xf5, 0xfc, 0x2e, 0x58, - 0x0a, 0xdd, 0x6b, 0x8e, 0xa0, 0x25, 0x52, 0x47, 0xe1, 0x89, 0xf8, 0xcd, 0x6f, 0x4f, 0x4b, 0xc8, - 0x1a, 0xc0, 0x84, 0xcd, 0x0e, 0x38, 0x13, 0x7c, 0xdf, 0xcf, 0xcd, 0xb7, 0xe4, 0x48, 0x9c, 0x27, - 0x6c, 0x36, 0x98, 0x45, 0x03, 0x81, 0xd6, 0x55, 0xa7, 0x05, 0x4d, 0x7e, 0x01, 0xce, 0x84, 0xcd, - 0xa4, 0x1f, 0xed, 0xfb, 0xda, 0xba, 0x4a, 0x06, 0xf9, 0x0c, 0x6a, 0xd9, 0x2c, 0xc2, 0xa0, 0x24, - 0xdf, 0x21, 0x99, 0x64, 0x0c, 0x66, 0x91, 0xf6, 0x38, 0x2a, 0x65, 0x39, 0xa0, 0x76, 0x09, 0x68, - 0x07, 0x6a, 0x5e, 0xe0, 0xe3, 0x43, 0xe4, 0x50, 0xf9, 0xb9, 0xfa, 0x47, 0x70, 0x6b, 0x01, 0x87, - 0xea, 0x3d, 0x2c, 0xab, 0x61, 0x77, 0xaa, 0xf7, 0x50, 0xaf, 0x62, 0xff, 0x43, 0x0d, 0x6e, 0x69, - 0x63, 0x38, 0x0f, 0x92, 0x7e, 0x26, 0xcd, 0xbe, 0x0b, 0x4d, 0x8c, 0x36, 0x3c, 0xd5, 0x36, 0x91, - 0x93, 0xe4, 0x0f, 0xc0, 0x42, 0x0f, 0xcc, 0xed, 0xf4, 0x7e, 0x89, 0x6a, 0x31, 0x5c, 0xd9, 0xad, - 0xbe, 0x12, 0xad, 0x4e, 0xbe, 0x81, 0xc6, 0x5b, 0x9e, 0xc6, 0x2a, 0x7a, 0xb6, 0xb6, 0xd6, 0xae, - 0x1b, 0x27, 0xef, 0x56, 0x0f, 0x53, 0xca, 0xff, 0x8f, 0xe0, 0x3f, 0x90, 0xf1, 0x72, 0x12, 0x5f, - 0x72, 0xbf, 0xdb, 0xc4, 0x1d, 0x55, 0xed, 0x23, 0x17, 0xe5, 0x68, 0xdb, 0x25, 0xda, 0x7b, 0xd0, - 0xaa, 0x1c, 0xef, 0x1a, 0xa4, 0xef, 0xcf, 0x5b, 0xbc, 0x53, 0x38, 0x72, 0xd5, 0x71, 0xf6, 0x00, - 0xca, 0xc3, 0xfe, 0x5f, 0xdd, 0xcf, 0xfd, 0x2b, 0x03, 0x6e, 0xed, 0xc6, 0x51, 0xc4, 0x31, 0x05, - 0x52, 0x57, 0x57, 0x9a, 0xbd, 0x71, 0xa3, 0xd9, 0x3f, 0x86, 0x86, 0x90, 0xca, 0x7a, 0xf6, 0xdb, - 0xd7, 0xdc, 0x05, 0x55, 0x1a, 0x32, 0xcc, 0x4c, 0xd8, 0x6c, 0x98, 0xf0, 0xc8, 0x0f, 0xa2, 0x71, - 0x1e, 0x66, 0x26, 0x6c, 0x76, 0xa2, 0x38, 0xee, 0x5f, 0x1b, 0x60, 0x29, 0x8f, 0x99, 0x8b, 0xd6, - 0xc6, 0x7c, 0xb4, 0xfe, 0x05, 0x38, 0x49, 0xca, 0xfd, 0xc0, 0xcb, 0x57, 0x75, 0x68, 0xc9, 0x90, - 0xc6, 0x79, 0x16, 0xa7, 0x1e, 0xc7, 0xe9, 0x6d, 0xaa, 0x08, 0xc9, 0x15, 0x09, 0xf3, 0x54, 0x1a, - 0x57, 0xa3, 0x8a, 0x90, 0x31, 0x5e, 0x5d, 0x0e, 0x5e, 0x8a, 0x4d, 0x35, 0xe5, 0xfe, 0x83, 0x09, - 0xed, 0xbd, 0x20, 0xe5, 0x5e, 0xc6, 0xfd, 0x9e, 0x3f, 0x46, 0x45, 0x1e, 0x65, 0x41, 0x76, 0xa5, - 0xdf, 0x13, 0x4d, 0x15, 0xcf, 0xbd, 0x39, 0x9f, 0xd2, 0x2a, 0xb8, 0x6b, 0x98, 0x85, 0x2b, 0x82, - 0x6c, 0x01, 0xa8, 0x44, 0x08, 0x33, 0xf1, 0xfa, 0xcd, 0x99, 0xb8, 0x83, 0x6a, 0xf2, 0x53, 0x62, - 0xa0, 0xc6, 0x04, 0xea, 0xad, 0xb1, 0x30, 0x4d, 0x9f, 0x4a, 0x5b, 0xc5, 0xfc, 0x61, 0xc4, 0x43, - 0xb4, 0x45, 0xcc, 0x1f, 0x46, 0x3c, 0x2c, 0xb2, 0xb6, 0xa6, 0xda, 0x8e, 0xfc, 0x26, 0x9f, 0x83, - 0x19, 0x27, 0x78, 0x3e, 0xbd, 0x60, 0xf5, 0x60, 0x9b, 0xc7, 0x09, 0x35, 0xe3, 0x44, 0x5e, 0xb4, - 0x4a, 0x3b, 0xbb, 0x8e, 0xb6, 0x5f, 0x19, 0x40, 0x30, 0x61, 0xa2, 0x5a, 0xe2, 0xde, 0x05, 0xf3, - 0x38, 0x21, 0x4d, 0xa8, 0xf5, 0x7b, 0x83, 0xce, 0x92, 0xfc, 0xd8, 0xeb, 0x1d, 0x74, 0x0c, 0xf7, - 0x9d, 0x01, 0xce, 0xe1, 0x34, 0x63, 0xd2, 0x6c, 0xc4, 0x87, 0xee, 0xed, 0x53, 0xb0, 0x45, 0xc6, - 0x52, 0x0c, 0xc2, 0x2a, 0x72, 0x34, 0x91, 0x1e, 0x08, 0xf2, 0x05, 0x34, 0xb8, 0x3f, 0xe6, 0xb9, - 0x43, 0x77, 0x16, 0xf7, 0x49, 0x95, 0x98, 0x6c, 0x80, 0x25, 0xbc, 0x73, 0x3e, 0x61, 0xdd, 0x7a, - 0xa9, 0xd8, 0x47, 0x8e, 0x7a, 0x64, 0xa9, 0x96, 0x63, 0x95, 0x90, 0xc6, 0x09, 0xa6, 0xcd, 0x0d, - 0x5d, 0x25, 0xa4, 0x71, 0x22, 0x93, 0xe6, 0x2d, 0xf8, 0x79, 0x30, 0x8e, 0xe2, 0x94, 0x0f, 0x83, - 0xc8, 0xe7, 0xb3, 0xa1, 0x17, 0x47, 0x67, 0x61, 0xe0, 0x65, 0x88, 0xa5, 0x4d, 0x6f, 0x2b, 0xe1, - 0xbe, 0x94, 0xed, 0x6a, 0x91, 0x3b, 0x03, 0x3b, 0x8f, 0x8b, 0xe4, 0xb1, 0x0c, 0x68, 0x18, 0x57, - 0xb5, 0x5b, 0x60, 0xda, 0x5f, 0x49, 0x70, 0x68, 0x2e, 0x97, 0xd7, 0x84, 0x6b, 0xe4, 0x91, 0x12, - 0x89, 0x6a, 0x7a, 0x55, 0xab, 0xa6, 0x57, 0x98, 0x29, 0xc6, 0x11, 0xd7, 0x19, 0x07, 0x7e, 0xbb, - 0x7f, 0x6b, 0x82, 0x5d, 0x3c, 0x65, 0x4f, 0xc1, 0x99, 0xe4, 0x50, 0x6b, 0x87, 0xc3, 0x5c, 0xba, - 0xc0, 0x9f, 0x96, 0x72, 0x72, 0x17, 0xcc, 0x8b, 0x4b, 0x0d, 0x94, 0x25, 0xb5, 0xbe, 0x7b, 0x43, - 0xcd, 0x8b, 0xcb, 0xd2, 0x63, 0x1b, 0x1f, 0xf5, 0xd8, 0x47, 0x70, 0xcb, 0x0b, 0x39, 0x8b, 0x86, - 0xa5, 0xc3, 0x29, 0x83, 0x5b, 0x41, 0xf6, 0x49, 0xe1, 0x75, 0x3a, 0xea, 0x34, 0xcb, 0xb7, 0xe5, - 0x21, 0x34, 0x7c, 0x1e, 0x66, 0xac, 0x5a, 0x1a, 0x1d, 0xa7, 0xcc, 0x0b, 0xf9, 0x9e, 0x64, 0x53, - 0x25, 0x25, 0x1b, 0x60, 0xe7, 0xef, 0xac, 0x2e, 0x88, 0x30, 0xf3, 0xce, 0xc1, 0xa6, 0x85, 0xb4, - 0xc4, 0x12, 0x2a, 0x58, 0xba, 0x5f, 0x41, 0xed, 0xbb, 0x37, 0x7d, 0x7d, 0x56, 0xe3, 0xbd, 0xb3, - 0xe6, 0x88, 0x9a, 0x15, 0x44, 0xff, 0xbb, 0x06, 0x4d, 0xed, 0x75, 0x72, 0xdf, 0xd3, 0x22, 0x4b, - 0x94, 0x9f, 0xf3, 0x8f, 0x5b, 0xe1, 0xbe, 0xd5, 0x32, 0xba, 0xf6, 0xf1, 0x32, 0x9a, 0xfc, 0x1a, - 0xda, 0x89, 0x92, 0x55, 0x1d, 0xfe, 0x93, 0xea, 0x18, 0xfd, 0x8b, 0xe3, 0x5a, 0x49, 0x49, 0x48, - 0xd3, 0xc5, 0x7a, 0x24, 0x63, 0x63, 0xbc, 0xa2, 0x36, 0x6d, 0x4a, 0x7a, 0xc0, 0xc6, 0x37, 0xb8, - 0xfd, 0x8f, 0xf0, 0x5e, 0x99, 0x0d, 0xc7, 0x49, 0xb7, 0x8d, 0x1e, 0x29, 0x3d, 0xbe, 0xea, 0x8c, - 0xcb, 0xf3, 0xce, 0x78, 0x0f, 0x1c, 0x2f, 0x9e, 0x4c, 0x02, 0x94, 0xad, 0xe8, 0x6c, 0x0f, 0x19, - 0x03, 0xe1, 0xfe, 0x8d, 0x01, 0x4d, 0x7d, 0x5a, 0xd2, 0x82, 0xe6, 0x5e, 0xef, 0xd5, 0xf6, 0xe9, - 0x81, 0x8c, 0x07, 0x00, 0xd6, 0xce, 0xfe, 0xd1, 0x36, 0xfd, 0xb3, 0x8e, 0x21, 0x63, 0xc3, 0xfe, - 0xd1, 0xa0, 0x63, 0x12, 0x07, 0x1a, 0xaf, 0x0e, 0x8e, 0xb7, 0x07, 0x9d, 0x1a, 0xb1, 0xa1, 0xbe, - 0x73, 0x7c, 0x7c, 0xd0, 0xa9, 0x93, 0x36, 0xd8, 0x7b, 0xdb, 0x83, 0xde, 0x60, 0xff, 0xb0, 0xd7, - 0x69, 0x48, 0xdd, 0xd7, 0xbd, 0xe3, 0x8e, 0x25, 0x3f, 0x4e, 0xf7, 0xf7, 0x3a, 0x4d, 0x29, 0x3f, - 0xd9, 0xee, 0xf7, 0x7f, 0x73, 0x4c, 0xf7, 0x3a, 0xb6, 0x9c, 0xb7, 0x3f, 0xa0, 0xfb, 0x47, 0xaf, - 0x3b, 0x8e, 0xfc, 0x3e, 0xde, 0xf9, 0xb6, 0xb7, 0x3b, 0xe8, 0x80, 0xfb, 0x15, 0xb4, 0x2a, 0x08, - 0xca, 0xd1, 0xb4, 0xf7, 0xaa, 0xb3, 0x24, 0x97, 0x7c, 0xb3, 0x7d, 0x70, 0xda, 0xeb, 0x18, 0x64, - 0x05, 0x00, 0x3f, 0x87, 0x07, 0xdb, 0x47, 0xaf, 0x3b, 0xa6, 0xfb, 0xfb, 0x60, 0x9f, 0x06, 0xfe, - 0x4e, 0x18, 0x7b, 0x17, 0xd2, 0x30, 0x46, 0x4c, 0x70, 0xfd, 0x4e, 0xe2, 0xb7, 0x8c, 0xf2, 0x68, - 0x94, 0x42, 0xdf, 0xbd, 0xa6, 0xdc, 0x23, 0x68, 0x9e, 0x06, 0xfe, 0x09, 0xf3, 0x2e, 0x64, 0x3d, - 0x3e, 0x92, 0xe3, 0x87, 0x22, 0x78, 0xcb, 0x75, 0x80, 0x73, 0x90, 0xd3, 0x0f, 0xde, 0x72, 0xf2, - 0x00, 0x2c, 0x24, 0xf2, 0x8c, 0x06, 0x6d, 0x39, 0x5f, 0x93, 0x6a, 0x99, 0x9b, 0x15, 0x5b, 0xc7, - 0x5a, 0xfb, 0x3e, 0xd4, 0x13, 0xe6, 0x5d, 0xe8, 0x60, 0xd2, 0xd2, 0x43, 0xe4, 0x72, 0x14, 0x05, - 0xe4, 0x11, 0xd8, 0xda, 0x3e, 0xf2, 0x79, 0x5b, 0x15, 0x43, 0xa2, 0x85, 0x70, 0xfe, 0xe6, 0x6a, - 0x0b, 0x37, 0xf7, 0x0d, 0x40, 0xd9, 0x9a, 0xb8, 0x26, 0xbb, 0xbe, 0x03, 0x0d, 0x16, 0x06, 0xfa, - 0xf0, 0x0e, 0x55, 0x84, 0x7b, 0x04, 0xad, 0x4a, 0x43, 0x43, 0x9a, 0x0d, 0x0b, 0xc3, 0xe1, 0x05, - 0xbf, 0x12, 0x38, 0xd6, 0xa6, 0x4d, 0x16, 0x86, 0xdf, 0xf1, 0x2b, 0x41, 0x1e, 0x40, 0x43, 0xf5, - 0x42, 0xcc, 0x85, 0x92, 0x1b, 0x87, 0x52, 0x25, 0x74, 0xbf, 0x04, 0x4b, 0xd5, 0xe1, 0x15, 0xab, - 0x35, 0x6e, 0x7c, 0x73, 0x5e, 0xea, 0x3d, 0x63, 0xd5, 0x4e, 0x9e, 0xea, 0x9e, 0x8b, 0x50, 0x1d, - 0x1e, 0xa3, 0x4c, 0xb5, 0x94, 0x92, 0x6e, 0xb7, 0xa0, 0xb2, 0xbb, 0x07, 0xf6, 0x07, 0xbb, 0x58, - 0x1a, 0x00, 0xb3, 0x04, 0xe0, 0x9a, 0xbe, 0x96, 0xfb, 0x5b, 0x80, 0xb2, 0x37, 0xa3, 0x9d, 0x48, - 0xcd, 0x22, 0x9d, 0xe8, 0x89, 0x2c, 0x8b, 0x82, 0xd0, 0x4f, 0x79, 0x34, 0x77, 0xea, 0xb2, 0x9b, - 0x53, 0xc8, 0xc9, 0x3a, 0xd4, 0xb1, 0xe5, 0x54, 0x2b, 0x83, 0x5c, 0xd1, 0x6f, 0x42, 0x89, 0x3b, - 0x82, 0x65, 0xf5, 0x94, 0x51, 0xfe, 0x97, 0x53, 0x2e, 0x3e, 0x98, 0x03, 0xad, 0x01, 0x14, 0x21, - 0x39, 0x6f, 0x9e, 0x55, 0x38, 0xd2, 0x94, 0xcf, 0x02, 0x1e, 0xfa, 0xf9, 0x69, 0x34, 0xe5, 0xfe, - 0x21, 0xb4, 0xf3, 0x35, 0xb0, 0x84, 0x7f, 0x5a, 0x3c, 0xa8, 0x0a, 0x4d, 0x55, 0x39, 0x28, 0x95, - 0xa3, 0xd8, 0xe7, 0x3b, 0x66, 0xd7, 0xc8, 0xdf, 0x54, 0xf7, 0xdf, 0x6a, 0xf9, 0x68, 0x5d, 0xd1, - 0xce, 0x65, 0x62, 0xc6, 0x62, 0x26, 0x36, 0x9f, 0xf2, 0x98, 0x3f, 0x2a, 0xe5, 0xf9, 0x15, 0x38, - 0x3e, 0xbe, 0xfb, 0xc1, 0x65, 0x1e, 0x68, 0x57, 0x17, 0xdf, 0x78, 0x9d, 0x19, 0x04, 0x97, 0x9c, - 0x96, 0xca, 0x72, 0x2f, 0x59, 0x7c, 0xc1, 0xa3, 0xe0, 0x2d, 0x96, 0xec, 0xf2, 0xd0, 0x25, 0xa3, - 0xec, 0x7f, 0xa8, 0x5c, 0x40, 0xf7, 0x3f, 0xf2, 0x56, 0x8e, 0x55, 0xb6, 0x72, 0x24, 0x72, 0xd3, - 0x44, 0xf0, 0x34, 0xcb, 0x73, 0x42, 0x45, 0x15, 0xb9, 0x95, 0xa3, 0x75, 0x65, 0x6e, 0xf5, 0x19, - 0xb4, 0xa3, 0x38, 0x1a, 0x46, 0xd3, 0x30, 0x94, 0x59, 0xab, 0xee, 0xcf, 0xb5, 0xa2, 0x38, 0x3a, - 0xd2, 0x2c, 0x59, 0xf4, 0x57, 0x55, 0x94, 0xe5, 0xb6, 0x54, 0xd1, 0x5f, 0xd1, 0x43, 0xfb, 0xde, - 0x80, 0x4e, 0x3c, 0xfa, 0x2d, 0xf7, 0x32, 0x44, 0x6c, 0x88, 0x26, 0xdb, 0x56, 0xcf, 0xad, 0xe2, - 0x4b, 0x88, 0x8e, 0xd8, 0x84, 0xbb, 0x2f, 0xc1, 0x29, 0x40, 0x90, 0x91, 0xf5, 0xe8, 0xf8, 0xa8, - 0xa7, 0x62, 0xdf, 0xfe, 0xd1, 0x5e, 0xef, 0x4f, 0x3b, 0x86, 0x8c, 0xcd, 0xb4, 0xf7, 0xa6, 0x47, - 0xfb, 0xbd, 0x8e, 0x29, 0xe3, 0xe6, 0x5e, 0xef, 0xa0, 0x37, 0xe8, 0x75, 0x6a, 0xdf, 0xd6, 0xed, - 0x66, 0xc7, 0xa6, 0x36, 0x9f, 0x25, 0x61, 0xe0, 0x05, 0x99, 0xdb, 0x07, 0x90, 0xd3, 0xea, 0x1b, - 0xbd, 0x07, 0x4e, 0xb9, 0xb6, 0xba, 0x51, 0x3b, 0xd3, 0xab, 0xca, 0xec, 0x4b, 0x1b, 0x95, 0x79, - 0x53, 0xf6, 0xa5, 0xcd, 0xec, 0x14, 0xec, 0x43, 0x96, 0xbc, 0x57, 0x90, 0xb4, 0x8b, 0xb2, 0x73, - 0xaa, 0x9b, 0x30, 0xfa, 0xd1, 0x7d, 0x08, 0x4d, 0x1d, 0xc4, 0xb4, 0x7f, 0xcc, 0x05, 0xb8, 0x5c, - 0x26, 0xeb, 0x83, 0x3b, 0x87, 0xf1, 0x25, 0x2f, 0xf2, 0x8e, 0x13, 0x76, 0x15, 0xc6, 0xcc, 0xff, - 0x88, 0x21, 0xfe, 0x12, 0x40, 0xc4, 0xd3, 0xd4, 0xe3, 0xc3, 0x71, 0xd1, 0xfb, 0x71, 0x14, 0xe7, - 0xb5, 0x6e, 0x28, 0x73, 0x91, 0xa1, 0xb0, 0xa6, 0xdc, 0x4c, 0xd2, 0x52, 0xf4, 0x73, 0xb0, 0xb2, - 0x59, 0x54, 0xb6, 0x9a, 0x1a, 0x99, 0xac, 0x06, 0xdd, 0x5d, 0x70, 0x06, 0x33, 0xac, 0x91, 0xa6, - 0x62, 0xee, 0x25, 0x35, 0x3e, 0xf0, 0x92, 0x9a, 0x0b, 0xf1, 0xf8, 0x3f, 0x0d, 0x68, 0x55, 0x12, - 0x22, 0xf2, 0x19, 0xd4, 0xb3, 0x59, 0x34, 0xdf, 0xa3, 0xcd, 0x17, 0xa1, 0x28, 0x92, 0xf6, 0x26, - 0x0b, 0x28, 0x26, 0x44, 0x30, 0x8e, 0xb8, 0xaf, 0xa7, 0x94, 0x45, 0xd5, 0xb6, 0x66, 0x91, 0x03, - 0xb8, 0xa5, 0x62, 0x46, 0xde, 0x9f, 0xc9, 0x73, 0xea, 0xcf, 0x17, 0x12, 0x30, 0x55, 0x47, 0xee, - 0xe6, 0x5a, 0xaa, 0x52, 0x5e, 0x19, 0xcf, 0x31, 0x57, 0xb7, 0xe1, 0xf6, 0x35, 0x6a, 0x3f, 0xa9, - 0x25, 0x70, 0x1f, 0x96, 0x65, 0x09, 0x1d, 0x4c, 0xb8, 0xc8, 0xd8, 0x24, 0xc1, 0x4c, 0x44, 0xc7, - 0xfc, 0x3a, 0x35, 0x33, 0xe1, 0x7e, 0x01, 0xed, 0x13, 0xce, 0x53, 0xca, 0x45, 0x12, 0x47, 0xea, - 0x15, 0x16, 0x78, 0x68, 0xfd, 0xc0, 0x68, 0xca, 0xfd, 0x0b, 0x70, 0x64, 0x8e, 0xbd, 0xc3, 0x32, - 0xef, 0xfc, 0xa7, 0xe4, 0xe0, 0x5f, 0x40, 0x33, 0x51, 0x66, 0xa2, 0x33, 0xe6, 0x36, 0xc6, 0x38, - 0x6d, 0x3a, 0x34, 0x17, 0xba, 0xdf, 0x40, 0xed, 0x68, 0x3a, 0xa9, 0xfe, 0x85, 0x52, 0x57, 0x7f, - 0xa1, 0xdc, 0x03, 0x07, 0xd3, 0x75, 0xec, 0xd7, 0xa9, 0x44, 0xd2, 0x96, 0x0c, 0x6c, 0xd4, 0x7d, - 0x0f, 0xad, 0x1c, 0xfb, 0x7d, 0x1f, 0xff, 0x07, 0xc1, 0xcb, 0xdf, 0xf7, 0xe7, 0x6c, 0x41, 0x55, - 0x6c, 0x3c, 0xf2, 0xf7, 0xf3, 0x4b, 0x53, 0xc4, 0xfc, 0xdc, 0xba, 0xe9, 0x50, 0xcc, 0xfd, 0x0a, - 0xda, 0x79, 0x1e, 0x7c, 0xc8, 0x33, 0x86, 0xe6, 0x14, 0x06, 0x3c, 0xaa, 0x98, 0x9a, 0xad, 0x18, - 0x03, 0xf1, 0x81, 0xf6, 0xa6, 0xbb, 0x09, 0x96, 0xb6, 0x55, 0x02, 0x75, 0x2f, 0xf6, 0x95, 0x8b, - 0x34, 0x28, 0x7e, 0xcb, 0x03, 0x4f, 0xc4, 0x38, 0x7f, 0x08, 0x27, 0x62, 0xec, 0xce, 0x60, 0x79, - 0x87, 0x79, 0x17, 0xd3, 0x24, 0x7f, 0x88, 0x2a, 0x05, 0x8b, 0x31, 0x57, 0xb0, 0x7c, 0xa0, 0xa7, - 0xfa, 0x09, 0x34, 0xa7, 0x51, 0x30, 0xcb, 0x33, 0x11, 0x87, 0x5a, 0x92, 0x54, 0xbd, 0xc4, 0x30, - 0xf6, 0xb0, 0x46, 0x41, 0xaf, 0x72, 0x68, 0x41, 0xbb, 0x7f, 0x0e, 0xcb, 0xbd, 0x59, 0x82, 0x1d, - 0xe6, 0x8f, 0x3e, 0x81, 0x95, 0x4d, 0x99, 0x73, 0x9b, 0x5a, 0x58, 0xb9, 0x96, 0xaf, 0xbc, 0xf5, - 0x4f, 0x06, 0xd4, 0xa5, 0x89, 0xc8, 0x32, 0xea, 0x8f, 0x39, 0x4b, 0xb3, 0x11, 0x67, 0x19, 0x99, - 0x33, 0x87, 0xd5, 0x39, 0xca, 0x5d, 0x7a, 0x61, 0x90, 0x2f, 0x55, 0xf3, 0x3a, 0xef, 0xc9, 0x2f, - 0xe7, 0x86, 0x86, 0x86, 0xb8, 0xa8, 0x4f, 0x36, 0xa1, 0xf5, 0x6d, 0x1c, 0x44, 0xbb, 0xaa, 0x9f, - 0x4b, 0x16, 0xcd, 0xf2, 0x3d, 0xfd, 0x67, 0x60, 0xed, 0x0b, 0x69, 0xff, 0xef, 0xab, 0x62, 0x78, - 0xad, 0xba, 0x86, 0xbb, 0xb4, 0xf5, 0x8f, 0x35, 0xa8, 0x7f, 0xcf, 0xd3, 0x98, 0x7c, 0x09, 0x4d, - 0xdd, 0xad, 0x21, 0x95, 0xae, 0xcc, 0x2a, 0xbe, 0xaf, 0x0b, 0x6d, 0x1c, 0x5c, 0xa5, 0xa3, 0x22, - 0x74, 0x59, 0xe7, 0x91, 0xb2, 0x99, 0xf4, 0xde, 0xa6, 0x5e, 0x42, 0xa7, 0x9f, 0xa5, 0x9c, 0x4d, - 0x2a, 0xea, 0xf3, 0x30, 0x5d, 0x57, 0x34, 0x22, 0x5a, 0x4f, 0xc1, 0x52, 0x41, 0x66, 0x61, 0xc0, - 0x62, 0xfd, 0x87, 0xca, 0x8f, 0xa0, 0xd5, 0x3f, 0x8f, 0xa7, 0xa1, 0xdf, 0xe7, 0xe9, 0x25, 0x27, - 0x95, 0x8e, 0xe9, 0x6a, 0xe5, 0xdb, 0x5d, 0x22, 0x1b, 0x00, 0xca, 0xcb, 0x4e, 0x03, 0x5f, 0x90, - 0xa6, 0x94, 0x1d, 0x4d, 0x27, 0x6a, 0xd2, 0x8a, 0xfb, 0x29, 0xcd, 0x4a, 0xac, 0xf9, 0x90, 0xe6, - 0xd7, 0xb0, 0xbc, 0x8b, 0xb1, 0xf8, 0x38, 0xdd, 0x1e, 0xc5, 0x69, 0x46, 0x16, 0xbb, 0xa6, 0xab, - 0x8b, 0x0c, 0x77, 0x89, 0xbc, 0x00, 0x7b, 0x90, 0x5e, 0x29, 0xfd, 0x9f, 0xe9, 0x10, 0x5d, 0xae, - 0x77, 0xcd, 0x29, 0xb7, 0xfe, 0xbe, 0x06, 0xd6, 0x6f, 0xe2, 0xf4, 0x82, 0xa7, 0xe4, 0x09, 0x58, - 0x58, 0xa8, 0x6b, 0x23, 0x2a, 0x8a, 0xf6, 0xeb, 0x16, 0x7a, 0x00, 0x0e, 0x82, 0x32, 0x60, 0xe2, - 0x42, 0x5d, 0x15, 0xfe, 0x89, 0xaa, 0x70, 0x51, 0xc9, 0x1b, 0xde, 0xeb, 0x8a, 0xba, 0xa8, 0xa2, - 0x39, 0x31, 0x57, 0x3d, 0xaf, 0x36, 0x55, 0x29, 0xdc, 0x77, 0x97, 0x36, 0x8c, 0x17, 0x06, 0x79, - 0x0c, 0xf5, 0xbe, 0x3a, 0xa9, 0x54, 0x2a, 0xff, 0x68, 0x5a, 0x5d, 0xc9, 0x19, 0xc5, 0xcc, 0xcf, - 0xc1, 0x52, 0x2f, 0xbb, 0x3a, 0xe6, 0x5c, 0x62, 0xba, 0xda, 0xa9, 0xb2, 0xf4, 0x80, 0xc7, 0x60, - 0xa9, 0xa0, 0xa1, 0x06, 0xcc, 0x05, 0x10, 0xb5, 0x6b, 0x15, 0x83, 0x94, 0xaa, 0xf2, 0x72, 0xa5, - 0x3a, 0xe7, 0xf1, 0x0b, 0xaa, 0xcf, 0xa0, 0x43, 0xb9, 0xc7, 0x83, 0xca, 0x9b, 0x4f, 0xf2, 0x43, - 0x2d, 0x9a, 0xed, 0x86, 0x41, 0x5e, 0xc2, 0xf2, 0x5c, 0x7e, 0x40, 0xba, 0x08, 0xf4, 0x35, 0x29, - 0xc3, 0xe2, 0xe0, 0x9d, 0xce, 0xbf, 0xbc, 0x5b, 0x33, 0xfe, 0xf5, 0xdd, 0x9a, 0xf1, 0xef, 0xef, - 0xd6, 0x8c, 0xdf, 0xfd, 0xc7, 0xda, 0xd2, 0xc8, 0xc2, 0x3f, 0xdf, 0xbf, 0xfe, 0xdf, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x3a, 0xde, 0xb8, 0x2c, 0xc0, 0x1f, 0x00, 0x00, + // 3329 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x39, 0x4b, 0x6f, 0x1b, 0xd7, + 0x7a, 0x9a, 0x21, 0x39, 0x9c, 0xf9, 0x48, 0xc9, 0xcc, 0xb1, 0xaf, 0xc3, 0x28, 0xf7, 0xca, 0xca, + 0xc4, 0x8e, 0x65, 0x3b, 0x96, 0x1d, 0x25, 0x6d, 0xaf, 0x6f, 0xd1, 0x85, 0x1e, 0xb4, 0xab, 0x44, + 0xaf, 0x1e, 0x52, 0xbe, 0x6d, 0x50, 0x94, 0x38, 0x9c, 0x39, 0xa2, 0x26, 0x1a, 0xce, 0x4c, 0xe7, + 0x0c, 0x05, 0xca, 0xbb, 0x2e, 0x5a, 0xf4, 0x27, 0x64, 0x51, 0x74, 0xd7, 0x4d, 0x37, 0xdd, 0x66, + 0xd9, 0x4d, 0x81, 0x2e, 0x8b, 0xfe, 0x82, 0x22, 0xed, 0x3f, 0x28, 0x50, 0xa0, 0xbb, 0xe2, 0x7c, + 0xe7, 0xcc, 0x83, 0xb4, 0x64, 0x27, 0x05, 0xee, 0x8a, 0xf3, 0x3d, 0xce, 0xeb, 0x7b, 0x7f, 0x1f, + 0xc1, 0x4e, 0x46, 0x9b, 0x49, 0x1a, 0x67, 0x31, 0x31, 0x93, 0xd1, 0xaa, 0xc3, 0x92, 0x40, 0x81, + 0xab, 0x0f, 0xc7, 0x41, 0x76, 0x3e, 0x1d, 0x6d, 0x7a, 0xf1, 0xe4, 0x99, 0x3f, 0x4e, 0x59, 0x72, + 0xfe, 0x34, 0x88, 0x9f, 0x8d, 0x98, 0x3f, 0xe6, 0xe9, 0xb3, 0x64, 0xf4, 0x2c, 0x5f, 0xe7, 0xae, + 0x42, 0xfd, 0x20, 0x10, 0x19, 0x21, 0x50, 0x9f, 0x06, 0xbe, 0xe8, 0x1a, 0xeb, 0xb5, 0x0d, 0x8b, + 0xe2, 0xb7, 0x7b, 0x08, 0xce, 0x80, 0x89, 0x8b, 0xd7, 0x2c, 0x9c, 0x72, 0xd2, 0x81, 0xda, 0x25, + 0x0b, 0xbb, 0xc6, 0xba, 0xb1, 0xd1, 0xa6, 0xf2, 0x93, 0x6c, 0x82, 0x7d, 0xc9, 0xc2, 0x61, 0x76, + 0x95, 0xf0, 0xae, 0xb9, 0x6e, 0x6c, 0xac, 0x6c, 0xdd, 0xde, 0x4c, 0x46, 0x9b, 0x27, 0xb1, 0xc8, + 0x82, 0x68, 0xbc, 0xf9, 0x9a, 0x85, 0x83, 0xab, 0x84, 0xd3, 0xe6, 0xa5, 0xfa, 0x70, 0x8f, 0xa1, + 0xd5, 0x4f, 0xbd, 0x97, 0xd3, 0xc8, 0xcb, 0x82, 0x38, 0x92, 0x27, 0x46, 0x6c, 0xc2, 0x71, 0x47, + 0x87, 0xe2, 0xb7, 0xc4, 0xb1, 0x74, 0x2c, 0xba, 0xb5, 0xf5, 0x9a, 0xc4, 0xc9, 0x6f, 0xd2, 0x85, + 0x66, 0x20, 0x76, 0xe3, 0x69, 0x94, 0x75, 0xeb, 0xeb, 0xc6, 0x86, 0x4d, 0x73, 0xd0, 0xfd, 0x6f, + 0x13, 0x1a, 0x7f, 0x32, 0xe5, 0xe9, 0x15, 0xae, 0xcb, 0xb2, 0x34, 0xdf, 0x4b, 0x7e, 0x93, 0x3b, + 0xd0, 0x08, 0x59, 0x34, 0x16, 0x5d, 0x13, 0x37, 0x53, 0x00, 0xf9, 0x18, 0x1c, 0x76, 0x96, 0xf1, + 0x74, 0x38, 0x0d, 0xfc, 0x6e, 0x6d, 0xdd, 0xd8, 0xb0, 0xa8, 0x8d, 0x88, 0xd3, 0xc0, 0x27, 0x1f, + 0x81, 0xed, 0xc7, 0x43, 0xaf, 0x7a, 0x96, 0x1f, 0xe3, 0x59, 0xe4, 0x53, 0xb0, 0xa7, 0x81, 0x3f, + 0x0c, 0x03, 0x91, 0x75, 0x1b, 0xeb, 0xc6, 0x46, 0x6b, 0xcb, 0x96, 0x8f, 0x95, 0xb2, 0xa3, 0xcd, + 0x69, 0xe0, 0xa3, 0x10, 0x1f, 0x83, 0x2d, 0x52, 0x6f, 0x78, 0x36, 0x8d, 0xbc, 0xae, 0x85, 0x4c, + 0xb7, 0x24, 0x53, 0xe5, 0xd5, 0xb4, 0x29, 0x14, 0x20, 0x9f, 0x95, 0xf2, 0x4b, 0x9e, 0x0a, 0xde, + 0x6d, 0xaa, 0xa3, 0x34, 0x48, 0x9e, 0x43, 0xeb, 0x8c, 0x79, 0x3c, 0x1b, 0x26, 0x2c, 0x65, 0x93, + 0xae, 0x5d, 0x6e, 0xf4, 0x52, 0xa2, 0x4f, 0x24, 0x56, 0x50, 0x38, 0x2b, 0x00, 0xf2, 0x25, 0x2c, + 0x23, 0x24, 0x86, 0x67, 0x41, 0x98, 0xf1, 0xb4, 0xeb, 0xe0, 0x9a, 0x15, 0x5c, 0x83, 0x98, 0x41, + 0xca, 0x39, 0x6d, 0x2b, 0x26, 0x85, 0x21, 0xbf, 0x02, 0xe0, 0xb3, 0x84, 0x45, 0xfe, 0x90, 0x85, + 0x61, 0x17, 0xf0, 0x0e, 0x8e, 0xc2, 0x6c, 0x87, 0x21, 0xf9, 0x50, 0xde, 0x8f, 0xf9, 0xc3, 0x4c, + 0x74, 0x97, 0xd7, 0x8d, 0x8d, 0x3a, 0xb5, 0x24, 0x38, 0x10, 0xee, 0x16, 0x38, 0x68, 0x11, 0xf8, + 0xe2, 0x07, 0x60, 0x5d, 0x4a, 0x40, 0x19, 0x4e, 0x6b, 0x6b, 0x59, 0x1e, 0x59, 0x18, 0x0d, 0xd5, + 0x44, 0x77, 0x0d, 0xec, 0x03, 0x16, 0x8d, 0x73, 0x4b, 0x93, 0xaa, 0xc0, 0x05, 0x0e, 0xc5, 0x6f, + 0xf7, 0x7b, 0x13, 0x2c, 0xca, 0xc5, 0x34, 0xcc, 0xc8, 0x43, 0x00, 0x29, 0xe8, 0x09, 0xcb, 0xd2, + 0x60, 0xa6, 0x77, 0x2d, 0x45, 0xed, 0x4c, 0x03, 0xff, 0x10, 0x49, 0xe4, 0x39, 0xb4, 0x71, 0xf7, + 0x9c, 0xd5, 0x2c, 0x2f, 0x50, 0xdc, 0x8f, 0xb6, 0x90, 0x45, 0xaf, 0xb8, 0x0b, 0x16, 0xea, 0x56, + 0xd9, 0xd7, 0x32, 0xd5, 0x10, 0x79, 0x00, 0x2b, 0x41, 0x94, 0x49, 0xd9, 0x7b, 0xd9, 0xd0, 0xe7, + 0x22, 0x57, 0xfe, 0x72, 0x81, 0xdd, 0xe3, 0x22, 0x23, 0x5f, 0x80, 0x12, 0x60, 0x7e, 0x60, 0x03, + 0x0f, 0x5c, 0x29, 0x14, 0x23, 0xd4, 0x89, 0xc8, 0xa3, 0x4f, 0x7c, 0x0a, 0x2d, 0xf9, 0xbe, 0x7c, + 0x85, 0x85, 0x2b, 0xda, 0xf8, 0x1a, 0x2d, 0x0e, 0x0a, 0x92, 0x41, 0xb3, 0x4b, 0xd1, 0x48, 0x03, + 0x53, 0x06, 0x81, 0xdf, 0x6e, 0x0f, 0x1a, 0xc7, 0xa9, 0xcf, 0xd3, 0x6b, 0x6d, 0x9c, 0x40, 0xdd, + 0xe7, 0xc2, 0x43, 0xf7, 0xb3, 0x29, 0x7e, 0x97, 0x76, 0x5f, 0xab, 0xd8, 0xbd, 0xfb, 0xf7, 0x06, + 0xb4, 0xfa, 0x71, 0x9a, 0x1d, 0x72, 0x21, 0xd8, 0x98, 0x93, 0x7b, 0xd0, 0x88, 0xe5, 0xb6, 0x5a, + 0xc2, 0x8e, 0xbc, 0x13, 0x9e, 0x43, 0x15, 0x7e, 0x41, 0x0f, 0xe6, 0xcd, 0x7a, 0xb8, 0x03, 0x0d, + 0xe5, 0x31, 0xd2, 0x9b, 0x1a, 0x54, 0x01, 0x52, 0xd6, 0xf1, 0xd9, 0x99, 0xe0, 0x4a, 0x96, 0x0d, + 0xaa, 0xa1, 0x9b, 0xcd, 0xea, 0xf7, 0x00, 0xe4, 0xfd, 0x7e, 0xa6, 0x15, 0xb8, 0xe7, 0xd0, 0xa2, + 0xec, 0x2c, 0xdb, 0x8d, 0xa3, 0x8c, 0xcf, 0x32, 0xb2, 0x02, 0x66, 0xe0, 0xa3, 0x88, 0x2c, 0x6a, + 0x06, 0xbe, 0xbc, 0xdc, 0x38, 0x8d, 0xa7, 0x09, 0x4a, 0x68, 0x99, 0x2a, 0x00, 0x45, 0xe9, 0xfb, + 0x29, 0xde, 0x58, 0x8a, 0xd2, 0xf7, 0x53, 0x72, 0x0f, 0x5a, 0x22, 0x62, 0x89, 0x38, 0x8f, 0x33, + 0x79, 0xb9, 0x3a, 0x5e, 0x0e, 0x72, 0xd4, 0x40, 0xb8, 0xff, 0x62, 0x80, 0x75, 0xc8, 0x27, 0x23, + 0x9e, 0xbe, 0x75, 0xca, 0x47, 0x60, 0xe3, 0xc6, 0xc3, 0xc0, 0xd7, 0x07, 0x35, 0x11, 0xde, 0xf7, + 0xaf, 0x3d, 0xea, 0x2e, 0x58, 0x21, 0x67, 0x52, 0xf8, 0xca, 0xce, 0x34, 0x24, 0x65, 0xc3, 0x26, + 0x43, 0x9f, 0x33, 0x1f, 0x43, 0x8c, 0x4d, 0x2d, 0x36, 0xd9, 0xe3, 0xcc, 0x97, 0x77, 0x0b, 0x99, + 0xc8, 0x86, 0xd3, 0xc4, 0x67, 0x19, 0xc7, 0xd0, 0x52, 0x97, 0x86, 0x23, 0xb2, 0x53, 0xc4, 0x90, + 0xc7, 0xf0, 0x81, 0x17, 0x4e, 0x85, 0x8c, 0x6b, 0x41, 0x74, 0x16, 0x0f, 0xe3, 0x28, 0xbc, 0x42, + 0xf9, 0xda, 0xf4, 0x96, 0x26, 0xec, 0x47, 0x67, 0xf1, 0x71, 0x14, 0x5e, 0xb9, 0x3f, 0x98, 0xd0, + 0x78, 0x85, 0x62, 0x78, 0x0e, 0xcd, 0x09, 0x3e, 0x28, 0xf7, 0xde, 0xbb, 0x52, 0xc2, 0x48, 0xdb, + 0x54, 0x2f, 0x15, 0xbd, 0x28, 0x4b, 0xaf, 0x68, 0xce, 0x26, 0x57, 0x64, 0x6c, 0x14, 0xf2, 0x4c, + 0x68, 0x8b, 0xa8, 0xac, 0x18, 0x28, 0x82, 0x5e, 0xa1, 0xd9, 0x16, 0xc5, 0x5a, 0x5b, 0x14, 0x2b, + 0x59, 0x05, 0xdb, 0x3b, 0xe7, 0xde, 0x85, 0x98, 0x4e, 0xb4, 0xd0, 0x0b, 0x78, 0xf5, 0x25, 0xb4, + 0xab, 0xf7, 0x90, 0x39, 0xe8, 0x82, 0x5f, 0xa1, 0xe0, 0xeb, 0x54, 0x7e, 0x92, 0x75, 0x68, 0xa0, + 0x87, 0xa3, 0xd8, 0x5b, 0x5b, 0x20, 0xaf, 0xa3, 0x96, 0x50, 0x45, 0xf8, 0x8d, 0xf9, 0x6b, 0x43, + 0xee, 0x53, 0xbd, 0x5d, 0x75, 0x1f, 0xe7, 0xe6, 0x7d, 0xd4, 0x92, 0xca, 0x3e, 0xee, 0xff, 0x9a, + 0xd0, 0xfe, 0x96, 0xa7, 0xf1, 0x49, 0x1a, 0x27, 0xb1, 0x60, 0x21, 0xd9, 0x9e, 0x7f, 0x9d, 0x92, + 0xe2, 0xba, 0x5c, 0x5c, 0x65, 0xdb, 0xec, 0x17, 0xcf, 0x55, 0xd2, 0xa9, 0xbe, 0xdf, 0x05, 0x4b, + 0x49, 0xf7, 0x9a, 0x27, 0x68, 0x8a, 0xe4, 0x51, 0xf2, 0x44, 0xf9, 0xcd, 0x5f, 0x4f, 0x53, 0xc8, + 0x1a, 0xc0, 0x84, 0xcd, 0x0e, 0x38, 0x13, 0x7c, 0xdf, 0xcf, 0xcd, 0xb7, 0xc4, 0x48, 0x39, 0x4f, + 0xd8, 0x6c, 0x30, 0x8b, 0x06, 0x02, 0xad, 0xab, 0x4e, 0x0b, 0x98, 0xfc, 0x12, 0x9c, 0x09, 0x9b, + 0x49, 0x3f, 0xda, 0xf7, 0xb5, 0x75, 0x95, 0x08, 0xf2, 0x09, 0xd4, 0xb2, 0x59, 0x84, 0x41, 0x49, + 0xe6, 0x21, 0x59, 0x64, 0x0c, 0x66, 0x91, 0xf6, 0x38, 0x2a, 0x69, 0xb9, 0x40, 0xed, 0x52, 0xa0, + 0x1d, 0xa8, 0x79, 0x81, 0x8f, 0x89, 0xc8, 0xa1, 0xf2, 0x73, 0xf5, 0x8f, 0xe0, 0xd6, 0x82, 0x1c, + 0xaa, 0x7a, 0x58, 0x56, 0xcb, 0xee, 0x54, 0xf5, 0x50, 0xaf, 0xca, 0xfe, 0x87, 0x1a, 0xdc, 0xd2, + 0xc6, 0x70, 0x1e, 0x24, 0xfd, 0x4c, 0x9a, 0x7d, 0x17, 0x9a, 0x18, 0x6d, 0x78, 0xaa, 0x6d, 0x22, + 0x07, 0xc9, 0x1f, 0x80, 0x85, 0x1e, 0x98, 0xdb, 0xe9, 0xbd, 0x52, 0xaa, 0xc5, 0x72, 0x65, 0xb7, + 0x5a, 0x25, 0x9a, 0x9d, 0x7c, 0x05, 0x8d, 0x37, 0x3c, 0x8d, 0x55, 0xf4, 0x6c, 0x6d, 0xad, 0x5d, + 0xb7, 0x4e, 0xea, 0x56, 0x2f, 0x53, 0xcc, 0xbf, 0x43, 0xe1, 0xdf, 0x97, 0xf1, 0x72, 0x12, 0x5f, + 0x72, 0xbf, 0xdb, 0xc4, 0x1b, 0x55, 0xed, 0x23, 0x27, 0xe5, 0xd2, 0xb6, 0x4b, 0x69, 0xef, 0x41, + 0xab, 0xf2, 0xbc, 0x6b, 0x24, 0x7d, 0x6f, 0xde, 0xe2, 0x9d, 0xc2, 0x91, 0xab, 0x8e, 0xb3, 0x07, + 0x50, 0x3e, 0xf6, 0xff, 0xeb, 0x7e, 0xee, 0x5f, 0x19, 0x70, 0x6b, 0x37, 0x8e, 0x22, 0x8e, 0x25, + 0x90, 0x52, 0x5d, 0x69, 0xf6, 0xc6, 0x8d, 0x66, 0xff, 0x08, 0x1a, 0x42, 0x32, 0xeb, 0xdd, 0x6f, + 0x5f, 0xa3, 0x0b, 0xaa, 0x38, 0x64, 0x98, 0x99, 0xb0, 0xd9, 0x30, 0xe1, 0x91, 0x1f, 0x44, 0xe3, + 0x3c, 0xcc, 0x4c, 0xd8, 0xec, 0x44, 0x61, 0xdc, 0xbf, 0x36, 0xc0, 0x52, 0x1e, 0x33, 0x17, 0xad, + 0x8d, 0xf9, 0x68, 0xfd, 0x4b, 0x70, 0x92, 0x94, 0xfb, 0x81, 0x97, 0x9f, 0xea, 0xd0, 0x12, 0x21, + 0x8d, 0xf3, 0x2c, 0x4e, 0x3d, 0x8e, 0xdb, 0xdb, 0x54, 0x01, 0x12, 0x2b, 0x12, 0xe6, 0xa9, 0x32, + 0xae, 0x46, 0x15, 0x20, 0x63, 0xbc, 0x52, 0x0e, 0x2a, 0xc5, 0xa6, 0x1a, 0x72, 0xff, 0xd1, 0x84, + 0xf6, 0x5e, 0x90, 0x72, 0x2f, 0xe3, 0x7e, 0xcf, 0x1f, 0x23, 0x23, 0x8f, 0xb2, 0x20, 0xbb, 0xd2, + 0xf9, 0x44, 0x43, 0x45, 0xba, 0x37, 0xe7, 0x4b, 0x5a, 0x25, 0xee, 0x1a, 0x56, 0xe1, 0x0a, 0x20, + 0x5b, 0x00, 0xaa, 0x10, 0xc2, 0x4a, 0xbc, 0x7e, 0x73, 0x25, 0xee, 0x20, 0x9b, 0xfc, 0x94, 0x32, + 0x50, 0x6b, 0x02, 0x95, 0x6b, 0x2c, 0x2c, 0xd3, 0xa7, 0xd2, 0x56, 0xb1, 0x7e, 0x18, 0xf1, 0x10, + 0x6d, 0x11, 0xeb, 0x87, 0x11, 0x0f, 0x8b, 0xaa, 0xad, 0xa9, 0xae, 0x23, 0xbf, 0xc9, 0xa7, 0x60, + 0xc6, 0x09, 0xbe, 0x4f, 0x1f, 0x58, 0x7d, 0xd8, 0xe6, 0x71, 0x42, 0xcd, 0x38, 0x91, 0x8a, 0x56, + 0x65, 0x67, 0xd7, 0xd1, 0xf6, 0x2b, 0x03, 0x08, 0x16, 0x4c, 0x54, 0x53, 0xdc, 0xbb, 0x60, 0x1e, + 0x27, 0xa4, 0x09, 0xb5, 0x7e, 0x6f, 0xd0, 0x59, 0x92, 0x1f, 0x7b, 0xbd, 0x83, 0x8e, 0xe1, 0xfe, + 0xad, 0x09, 0xce, 0xe1, 0x34, 0x63, 0xd2, 0x6c, 0xc4, 0xbb, 0xf4, 0xf6, 0x11, 0xd8, 0x22, 0x63, + 0x29, 0x06, 0x61, 0x15, 0x39, 0x9a, 0x08, 0x0f, 0x04, 0xf9, 0x0c, 0x1a, 0xdc, 0x1f, 0xf3, 0xdc, + 0xa1, 0x3b, 0x8b, 0xf7, 0xa4, 0x8a, 0x4c, 0x36, 0xc0, 0x12, 0xde, 0x39, 0x9f, 0xb0, 0x6e, 0xbd, + 0x64, 0xec, 0x23, 0x46, 0x25, 0x59, 0xaa, 0xe9, 0xd8, 0x25, 0xa4, 0x71, 0x82, 0x65, 0x73, 0x43, + 0x77, 0x09, 0x69, 0x9c, 0xc8, 0xa2, 0x79, 0x0b, 0x7e, 0x11, 0x8c, 0xa3, 0x38, 0xe5, 0xc3, 0x20, + 0xf2, 0xf9, 0x6c, 0xe8, 0xc5, 0xd1, 0x59, 0x18, 0x78, 0x19, 0xca, 0xd2, 0xa6, 0xb7, 0x15, 0x71, + 0x5f, 0xd2, 0x76, 0x35, 0x89, 0xdc, 0x87, 0x86, 0x54, 0x9c, 0xd0, 0xfe, 0x8d, 0xf5, 0xa4, 0xd4, + 0x91, 0x3e, 0x55, 0x11, 0xdd, 0x19, 0xd8, 0x79, 0xf4, 0x24, 0x8f, 0x64, 0xd8, 0xc3, 0xe8, 0xab, + 0x9d, 0x07, 0x9b, 0x83, 0x4a, 0x19, 0x44, 0x73, 0xba, 0x54, 0x26, 0xde, 0x24, 0x8f, 0xa7, 0x08, + 0x54, 0x8b, 0xb0, 0x5a, 0xb5, 0x08, 0xc3, 0x7a, 0x32, 0x8e, 0xb8, 0xae, 0x4b, 0xf0, 0xdb, 0xfd, + 0x3b, 0x13, 0xec, 0x22, 0xe1, 0x3d, 0x01, 0x67, 0x92, 0x2b, 0x44, 0xbb, 0x25, 0x56, 0xdc, 0x85, + 0x96, 0x68, 0x49, 0x27, 0x77, 0xc1, 0xbc, 0xb8, 0xd4, 0xe2, 0xb4, 0x24, 0xd7, 0x37, 0xaf, 0xa9, + 0x79, 0x71, 0x59, 0xfa, 0x75, 0xe3, 0xbd, 0x7e, 0xfd, 0x10, 0x6e, 0x79, 0x21, 0x67, 0xd1, 0xb0, + 0x74, 0x4b, 0x65, 0x96, 0x2b, 0x88, 0x3e, 0x29, 0x7c, 0x53, 0xc7, 0xa6, 0x66, 0x99, 0x81, 0x1e, + 0x40, 0xc3, 0xe7, 0x61, 0xc6, 0xaa, 0x0d, 0xd4, 0x71, 0xca, 0xbc, 0x90, 0xef, 0x49, 0x34, 0x55, + 0x54, 0xb2, 0x01, 0x76, 0x9e, 0x8d, 0x75, 0xdb, 0x84, 0xf5, 0x79, 0x2e, 0x6c, 0x5a, 0x50, 0x4b, + 0x59, 0x42, 0x45, 0x96, 0xee, 0x17, 0x50, 0xfb, 0xe6, 0x75, 0x5f, 0xbf, 0xd5, 0x78, 0xeb, 0xad, + 0xb9, 0x44, 0xcd, 0x8a, 0x44, 0xff, 0xa7, 0x06, 0x4d, 0xed, 0x9b, 0xf2, 0xde, 0xd3, 0xa2, 0x96, + 0x94, 0x9f, 0xf3, 0x29, 0xb0, 0x70, 0xf2, 0x6a, 0xb3, 0x5d, 0x7b, 0x7f, 0xb3, 0x4d, 0x7e, 0x03, + 0xed, 0x44, 0xd1, 0xaa, 0x61, 0xe1, 0xc3, 0xea, 0x1a, 0xfd, 0x8b, 0xeb, 0x5a, 0x49, 0x09, 0x48, + 0x03, 0xc7, 0xae, 0x25, 0x63, 0x63, 0x54, 0x51, 0x9b, 0x36, 0x25, 0x3c, 0x60, 0xe3, 0x1b, 0x82, + 0xc3, 0x4f, 0xf0, 0x71, 0x59, 0x33, 0xc7, 0x49, 0xb7, 0x8d, 0x7e, 0x2b, 0xe3, 0x42, 0xd5, 0x65, + 0x97, 0xe7, 0x5d, 0xf6, 0x63, 0x70, 0xbc, 0x78, 0x32, 0x09, 0x90, 0xb6, 0xa2, 0x6b, 0x42, 0x44, + 0x0c, 0x84, 0xfb, 0x37, 0x06, 0x34, 0xf5, 0x6b, 0x49, 0x0b, 0x9a, 0x7b, 0xbd, 0x97, 0xdb, 0xa7, + 0x07, 0x32, 0x6a, 0x00, 0x58, 0x3b, 0xfb, 0x47, 0xdb, 0xf4, 0xcf, 0x3a, 0x86, 0x8c, 0x20, 0xfb, + 0x47, 0x83, 0x8e, 0x49, 0x1c, 0x68, 0xbc, 0x3c, 0x38, 0xde, 0x1e, 0x74, 0x6a, 0xc4, 0x86, 0xfa, + 0xce, 0xf1, 0xf1, 0x41, 0xa7, 0x4e, 0xda, 0x60, 0xef, 0x6d, 0x0f, 0x7a, 0x83, 0xfd, 0xc3, 0x5e, + 0xa7, 0x21, 0x79, 0x5f, 0xf5, 0x8e, 0x3b, 0x96, 0xfc, 0x38, 0xdd, 0xdf, 0xeb, 0x34, 0x25, 0xfd, + 0x64, 0xbb, 0xdf, 0xff, 0xed, 0x31, 0xdd, 0xeb, 0xd8, 0x72, 0xdf, 0xfe, 0x80, 0xee, 0x1f, 0xbd, + 0xea, 0x38, 0xf2, 0xfb, 0x78, 0xe7, 0xeb, 0xde, 0xee, 0xa0, 0x03, 0xee, 0x17, 0xd0, 0xaa, 0x48, + 0x50, 0xae, 0xa6, 0xbd, 0x97, 0x9d, 0x25, 0x79, 0xe4, 0xeb, 0xed, 0x83, 0xd3, 0x5e, 0xc7, 0x20, + 0x2b, 0x00, 0xf8, 0x39, 0x3c, 0xd8, 0x3e, 0x7a, 0xd5, 0x31, 0xdd, 0xdf, 0x07, 0xfb, 0x34, 0xf0, + 0x77, 0xc2, 0xd8, 0xbb, 0x90, 0x86, 0x31, 0x62, 0x82, 0xeb, 0x6c, 0x8a, 0xdf, 0x32, 0x17, 0xa0, + 0x51, 0x0a, 0xad, 0x7b, 0x0d, 0xb9, 0x47, 0xd0, 0x3c, 0x0d, 0xfc, 0x13, 0xe6, 0x5d, 0xc8, 0xae, + 0x7d, 0x24, 0xd7, 0x0f, 0x45, 0xf0, 0x86, 0xeb, 0x30, 0xe8, 0x20, 0xa6, 0x1f, 0xbc, 0xe1, 0xe4, + 0x3e, 0x58, 0x08, 0xe4, 0x75, 0x0f, 0xda, 0x72, 0x7e, 0x26, 0xd5, 0x34, 0x37, 0x2b, 0xae, 0x8e, + 0x1d, 0xf9, 0x3d, 0xa8, 0x27, 0xcc, 0xbb, 0xd0, 0xc1, 0xa4, 0xa5, 0x97, 0xc8, 0xe3, 0x28, 0x12, + 0xc8, 0x43, 0xb0, 0xb5, 0x7d, 0xe4, 0xfb, 0xb6, 0x2a, 0x86, 0x44, 0x0b, 0xe2, 0xbc, 0xe6, 0x6a, + 0x0b, 0x9a, 0xfb, 0x0a, 0xa0, 0x1c, 0x60, 0x5c, 0x53, 0x83, 0xdf, 0x81, 0x06, 0x0b, 0x03, 0xfd, + 0x78, 0x87, 0x2a, 0xc0, 0x3d, 0x82, 0x56, 0x65, 0xec, 0x21, 0xcd, 0x86, 0x85, 0xe1, 0xf0, 0x82, + 0x5f, 0x09, 0x5c, 0x6b, 0xd3, 0x26, 0x0b, 0xc3, 0x6f, 0xf8, 0x95, 0x90, 0x81, 0x54, 0x4d, 0x4c, + 0xcc, 0x85, 0xc6, 0x1c, 0x97, 0x52, 0x45, 0x74, 0x3f, 0x07, 0x4b, 0x75, 0xeb, 0x15, 0xab, 0x35, + 0x6e, 0xcc, 0x4c, 0x2f, 0xf4, 0x9d, 0xb1, 0xb7, 0x27, 0x4f, 0xf4, 0x64, 0x46, 0xa8, 0x39, 0x90, + 0x51, 0x16, 0x64, 0x8a, 0x49, 0x0f, 0x65, 0x90, 0xd9, 0xdd, 0x03, 0xfb, 0x9d, 0xb3, 0x2e, 0x2d, + 0x00, 0xb3, 0x14, 0xc0, 0x35, 0xd3, 0x2f, 0xf7, 0x3b, 0x80, 0x72, 0x82, 0xa3, 0x9d, 0x48, 0xed, + 0x22, 0x9d, 0xe8, 0xb1, 0x6c, 0x9e, 0x82, 0xd0, 0x4f, 0x79, 0x34, 0xf7, 0xea, 0x72, 0xe6, 0x53, + 0xd0, 0xc9, 0x3a, 0xd4, 0x71, 0x30, 0x55, 0x2b, 0x83, 0x5c, 0x31, 0x95, 0x42, 0x8a, 0x3b, 0x83, + 0x65, 0x95, 0xf0, 0x28, 0xff, 0xcb, 0x29, 0x17, 0xef, 0xac, 0x94, 0xd6, 0x00, 0x8a, 0x90, 0x9c, + 0x8f, 0xd8, 0x2a, 0x18, 0x69, 0xca, 0x67, 0x01, 0x0f, 0xfd, 0xfc, 0x35, 0x1a, 0x92, 0x4a, 0x56, + 0xd9, 0xae, 0xae, 0xa6, 0x13, 0x2a, 0xbb, 0xfd, 0x21, 0xb4, 0xf3, 0x93, 0xb1, 0xfd, 0x7f, 0x52, + 0x24, 0x63, 0x25, 0x63, 0xd5, 0x75, 0x28, 0x96, 0xa3, 0xd8, 0xe7, 0x3b, 0x66, 0xd7, 0xc8, 0xf3, + 0xb1, 0xfb, 0xef, 0xb5, 0x7c, 0xb5, 0xee, 0x86, 0xe7, 0xaa, 0x38, 0x63, 0xb1, 0x8a, 0x9b, 0x2f, + 0x97, 0xcc, 0x9f, 0x54, 0x2e, 0xfd, 0x1a, 0x1c, 0x1f, 0x6b, 0x86, 0xe0, 0x32, 0x0f, 0xbf, 0xab, + 0x8b, 0xf5, 0x81, 0xae, 0x2a, 0x82, 0x4b, 0x4e, 0x4b, 0x66, 0x79, 0x97, 0x2c, 0xbe, 0xe0, 0x51, + 0xf0, 0x06, 0xdb, 0x7d, 0xf9, 0xe6, 0x12, 0x51, 0xce, 0x4e, 0x54, 0x1d, 0xa1, 0x67, 0x27, 0xf9, + 0x18, 0xc8, 0x2a, 0xc7, 0x40, 0x52, 0x9e, 0xd3, 0x44, 0xf0, 0x34, 0xcb, 0xeb, 0x49, 0x05, 0x15, + 0x75, 0x99, 0xa3, 0x79, 0x65, 0x5d, 0xf6, 0x09, 0xb4, 0xa3, 0x38, 0x1a, 0x46, 0xd3, 0x30, 0x94, + 0x15, 0xaf, 0x9e, 0xed, 0xb5, 0xa2, 0x38, 0x3a, 0xd2, 0x28, 0xf2, 0x18, 0x3e, 0xa8, 0xb2, 0x28, + 0x7b, 0x6e, 0xa9, 0x81, 0x41, 0x85, 0x0f, 0xad, 0x7e, 0x03, 0x3a, 0xf1, 0xe8, 0x3b, 0xee, 0x65, + 0x28, 0xb1, 0x21, 0x1a, 0x72, 0x5b, 0x25, 0x61, 0x85, 0x97, 0x22, 0x3a, 0x62, 0x13, 0xee, 0xbe, + 0x00, 0xa7, 0x10, 0x82, 0x8c, 0xb7, 0x47, 0xc7, 0x47, 0x3d, 0x15, 0x11, 0xf7, 0x8f, 0xf6, 0x7a, + 0x7f, 0xda, 0x31, 0x64, 0xc4, 0xa6, 0xbd, 0xd7, 0x3d, 0xda, 0xef, 0x75, 0x4c, 0x19, 0x4d, 0xf7, + 0x7a, 0x07, 0xbd, 0x41, 0xaf, 0x53, 0xfb, 0xba, 0x6e, 0x37, 0x3b, 0x36, 0xb5, 0xf9, 0x2c, 0x09, + 0x03, 0x2f, 0xc8, 0xdc, 0x3e, 0x40, 0x59, 0x04, 0xc9, 0xb8, 0x52, 0x9e, 0xad, 0x34, 0x6a, 0x67, + 0xfa, 0x54, 0x59, 0xb9, 0x69, 0x53, 0x33, 0x6f, 0xaa, 0xdc, 0x14, 0xdd, 0x3d, 0x05, 0xfb, 0x90, + 0x25, 0x6f, 0x35, 0x33, 0xed, 0xa2, 0x65, 0x9d, 0xea, 0x01, 0x8e, 0x4e, 0xc5, 0x0f, 0xa0, 0xa9, + 0x43, 0x9b, 0xf6, 0x9a, 0xb9, 0xb0, 0x97, 0xd3, 0x64, 0x6f, 0x71, 0xe7, 0x30, 0xbe, 0xe4, 0x45, + 0x35, 0x72, 0xc2, 0xae, 0xc2, 0x98, 0xf9, 0xef, 0x31, 0xc4, 0x5f, 0x01, 0x88, 0x78, 0x9a, 0x7a, + 0x7c, 0x38, 0x2e, 0xe6, 0x46, 0x8e, 0xc2, 0xbc, 0xd2, 0xc3, 0x68, 0x2e, 0x32, 0x24, 0xd6, 0x94, + 0xf3, 0x49, 0x58, 0x92, 0x7e, 0x01, 0x56, 0x36, 0x8b, 0xca, 0x31, 0x55, 0x23, 0x93, 0x9d, 0xa4, + 0xbb, 0x0b, 0xce, 0x60, 0x86, 0xfd, 0xd5, 0x54, 0xcc, 0xe5, 0x57, 0xe3, 0x1d, 0xf9, 0xd5, 0x5c, + 0x88, 0xd2, 0xff, 0x65, 0x40, 0xab, 0x52, 0x26, 0x91, 0x4f, 0xa0, 0x9e, 0xcd, 0xa2, 0xf9, 0xf9, + 0x6e, 0x7e, 0x08, 0x45, 0x92, 0xb4, 0x37, 0xd9, 0x7c, 0x31, 0x21, 0x82, 0x71, 0xc4, 0x7d, 0xbd, + 0xa5, 0x6c, 0xc8, 0xb6, 0x35, 0x8a, 0x1c, 0xc0, 0x2d, 0x15, 0x49, 0xf2, 0xd9, 0x4e, 0x5e, 0x8f, + 0x7f, 0xba, 0x50, 0x96, 0xa9, 0x1e, 0x74, 0x37, 0xe7, 0x52, 0x5d, 0xf6, 0xca, 0x78, 0x0e, 0xb9, + 0xba, 0x0d, 0xb7, 0xaf, 0x61, 0xfb, 0x59, 0xe3, 0x84, 0x7b, 0xb0, 0x2c, 0xdb, 0xef, 0x60, 0xc2, + 0x45, 0xc6, 0x26, 0x09, 0xd6, 0x27, 0x3a, 0x13, 0xd4, 0xa9, 0x99, 0x09, 0xf7, 0x33, 0x68, 0x9f, + 0x70, 0x9e, 0x52, 0x2e, 0x92, 0x38, 0x52, 0xb9, 0x59, 0xe0, 0xa3, 0x75, 0xda, 0xd1, 0x90, 0xfb, + 0x17, 0xe0, 0xc8, 0xca, 0x7b, 0x87, 0x65, 0xde, 0xf9, 0xcf, 0xa9, 0xcc, 0x3f, 0x83, 0x66, 0xa2, + 0xcc, 0x44, 0xd7, 0xd1, 0x6d, 0x8c, 0x71, 0xda, 0x74, 0x68, 0x4e, 0x74, 0xbf, 0x82, 0xda, 0xd1, + 0x74, 0x52, 0xfd, 0xfb, 0xa5, 0xae, 0xfe, 0x7e, 0xf9, 0x18, 0x1c, 0x2c, 0xe2, 0x71, 0xd6, 0xa7, + 0xca, 0x4b, 0x5b, 0x22, 0x70, 0xc8, 0xf7, 0x2d, 0xb4, 0x72, 0xd9, 0xef, 0xfb, 0xf8, 0x1f, 0x0a, + 0x2a, 0x7f, 0xdf, 0x9f, 0xb3, 0x05, 0xd5, 0xed, 0xf1, 0xc8, 0xdf, 0xcf, 0x95, 0xa6, 0x80, 0xf9, + 0xbd, 0xf5, 0xc0, 0xa2, 0xd8, 0xfb, 0x25, 0xb4, 0xf3, 0xea, 0xf8, 0x90, 0x67, 0x0c, 0xcd, 0x29, + 0x0c, 0x78, 0x54, 0x31, 0x35, 0x5b, 0x21, 0x06, 0xe2, 0x1d, 0xa3, 0x51, 0x77, 0x13, 0x2c, 0x6d, + 0xab, 0x04, 0xea, 0x5e, 0xec, 0x2b, 0x17, 0x69, 0x50, 0xfc, 0x96, 0x0f, 0x9e, 0x88, 0x71, 0x9e, + 0x1e, 0x27, 0x62, 0x2c, 0xd3, 0xd3, 0x0e, 0xf3, 0x2e, 0xa6, 0x49, 0x9e, 0x9e, 0x2a, 0x6d, 0x8c, + 0x31, 0xd7, 0xc6, 0xbc, 0x63, 0x1e, 0xfb, 0x21, 0x34, 0xa7, 0x51, 0x30, 0xcb, 0xeb, 0x13, 0x87, + 0x5a, 0x12, 0x54, 0x73, 0xc8, 0x30, 0xf6, 0xb0, 0x73, 0x41, 0xaf, 0x72, 0x68, 0x01, 0xbb, 0x7f, + 0x0e, 0xcb, 0xbd, 0x59, 0x82, 0xd3, 0xe9, 0xf7, 0x26, 0xc6, 0xca, 0xa5, 0xcc, 0xb9, 0x4b, 0x2d, + 0x9c, 0x5c, 0xcb, 0x4f, 0xde, 0xfa, 0x67, 0x03, 0xea, 0xd2, 0x44, 0x64, 0x73, 0xf5, 0xc7, 0x9c, + 0xa5, 0xd9, 0x88, 0xb3, 0x8c, 0xcc, 0x99, 0xc3, 0xea, 0x1c, 0xe4, 0x2e, 0x3d, 0x37, 0xc8, 0xe7, + 0x6a, 0xf0, 0x9d, 0xcf, 0xf3, 0x97, 0x73, 0x43, 0x43, 0x43, 0x5c, 0xe4, 0x27, 0x9b, 0xd0, 0xfa, + 0x3a, 0x0e, 0xa2, 0x5d, 0x35, 0x0b, 0x26, 0x8b, 0x66, 0xf9, 0x16, 0xff, 0x53, 0xb0, 0xf6, 0x85, + 0xb4, 0xff, 0xb7, 0x59, 0x31, 0xbc, 0x56, 0x5d, 0xc3, 0x5d, 0xda, 0xfa, 0xa7, 0x1a, 0xd4, 0xbf, + 0xe5, 0x69, 0x4c, 0x3e, 0x87, 0xa6, 0x9e, 0xf4, 0x90, 0xca, 0x44, 0x67, 0x15, 0xf3, 0xeb, 0xc2, + 0x08, 0x08, 0x4f, 0xe9, 0xa8, 0x08, 0x5d, 0x76, 0x7f, 0xa4, 0x1c, 0x44, 0xbd, 0x75, 0xa9, 0x17, + 0xd0, 0xe9, 0x67, 0x29, 0x67, 0x93, 0x0a, 0xfb, 0xbc, 0x98, 0xae, 0x6b, 0x25, 0x51, 0x5a, 0x4f, + 0xc0, 0x52, 0x41, 0x66, 0x61, 0xc1, 0x62, 0x57, 0x88, 0xcc, 0x0f, 0xa1, 0xd5, 0x3f, 0x8f, 0xa7, + 0xa1, 0xdf, 0xe7, 0xe9, 0x25, 0x27, 0x95, 0x69, 0xeb, 0x6a, 0xe5, 0xdb, 0x5d, 0x22, 0x1b, 0x00, + 0xca, 0xcb, 0x4e, 0x03, 0x5f, 0x90, 0xa6, 0xa4, 0x1d, 0x4d, 0x27, 0x6a, 0xd3, 0x8a, 0xfb, 0x29, + 0xce, 0x4a, 0xac, 0x79, 0x17, 0xe7, 0x97, 0xb0, 0xbc, 0x8b, 0xb1, 0xf8, 0x38, 0xdd, 0x1e, 0xc5, + 0x69, 0x46, 0x16, 0x27, 0xae, 0xab, 0x8b, 0x08, 0x77, 0x89, 0x3c, 0x07, 0x7b, 0x90, 0x5e, 0x29, + 0xfe, 0x0f, 0x74, 0x88, 0x2e, 0xcf, 0xbb, 0xe6, 0x95, 0x5b, 0xff, 0x50, 0x03, 0xeb, 0xb7, 0x71, + 0x7a, 0xc1, 0x53, 0xf2, 0x18, 0x2c, 0x6c, 0xdf, 0xb5, 0x11, 0x15, 0xad, 0xfc, 0x75, 0x07, 0xdd, + 0x07, 0x07, 0x85, 0x32, 0x60, 0xe2, 0x42, 0xa9, 0x0a, 0xff, 0x80, 0x55, 0x72, 0x51, 0xc5, 0x1b, + 0xea, 0x75, 0x45, 0x29, 0xaa, 0x18, 0x59, 0xcc, 0xf5, 0xd4, 0xab, 0x4d, 0xd5, 0x20, 0xf7, 0xdd, + 0xa5, 0x0d, 0xe3, 0xb9, 0x41, 0x1e, 0x41, 0xbd, 0xaf, 0x5e, 0x2a, 0x99, 0xca, 0x3f, 0xa9, 0x56, + 0x57, 0x72, 0x44, 0xb1, 0xf3, 0x33, 0xb0, 0x54, 0x66, 0x57, 0xcf, 0x9c, 0x2b, 0x57, 0x57, 0x3b, + 0x55, 0x94, 0x5e, 0xf0, 0x08, 0x2c, 0x15, 0x34, 0xd4, 0x82, 0xb9, 0x00, 0xa2, 0x6e, 0xad, 0x62, + 0x90, 0x62, 0x55, 0x5e, 0xae, 0x58, 0xe7, 0x3c, 0x7e, 0x81, 0xf5, 0x29, 0x74, 0x28, 0xf7, 0x78, + 0x50, 0xc9, 0xf9, 0x24, 0x7f, 0xd4, 0xa2, 0xd9, 0x6e, 0x18, 0xe4, 0x05, 0x2c, 0xcf, 0xd5, 0x07, + 0xa4, 0x8b, 0x82, 0xbe, 0xa6, 0x64, 0x58, 0x5c, 0xbc, 0xd3, 0xf9, 0xd7, 0x1f, 0xd7, 0x8c, 0x7f, + 0xfb, 0x71, 0xcd, 0xf8, 0x8f, 0x1f, 0xd7, 0x8c, 0xef, 0xff, 0x73, 0x6d, 0x69, 0x64, 0xe1, 0x1f, + 0xf7, 0x5f, 0xfe, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x60, 0xfc, 0x15, 0x14, 0xfc, 0x1f, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -6028,6 +6046,18 @@ func (m *Mutations) MarshalTo(dAtA []byte) (int, error) { } i++ } + if len(m.Types) > 0 { + for _, msg := range m.Types { + dAtA[i] = 0x3a + i++ + i = encodeVarintPb(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } if m.XXX_unrecognized != nil { i += copy(dAtA[i:], m.XXX_unrecognized) } @@ -6707,6 +6737,21 @@ func (m *SchemaRequest) MarshalTo(dAtA []byte) (int, error) { i += copy(dAtA[i:], s) } } + if len(m.Types) > 0 { + for _, s := range m.Types { + dAtA[i] = 0x22 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } if m.XXX_unrecognized != nil { i += copy(dAtA[i:], m.XXX_unrecognized) } @@ -8017,6 +8062,12 @@ func (m *Mutations) Size() (n int) { if m.IgnoreIndexConflict { n += 2 } + if len(m.Types) > 0 { + for _, e := range m.Types { + l = e.Size() + n += 1 + l + sovPb(uint64(l)) + } + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -8377,6 +8428,12 @@ func (m *SchemaRequest) Size() (n int) { n += 1 + l + sovPb(uint64(l)) } } + if len(m.Types) > 0 { + for _, s := range m.Types { + l = len(s) + n += 1 + l + sovPb(uint64(l)) + } + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -12382,6 +12439,37 @@ func (m *Mutations) Unmarshal(dAtA []byte) error { } } m.IgnoreIndexConflict = bool(v != 0) + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Types", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPb + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Types = append(m.Types, &TypeUpdate{}) + if err := m.Types[len(m.Types)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipPb(dAtA[iNdEx:]) @@ -14316,6 +14404,35 @@ func (m *SchemaRequest) Unmarshal(dAtA []byte) error { } m.Fields = append(m.Fields, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Types", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthPb + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Types = append(m.Types, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipPb(dAtA[iNdEx:]) diff --git a/query/common_test.go b/query/common_test.go index 8bdce97a85a..fe89fdbdd7e 100644 --- a/query/common_test.go +++ b/query/common_test.go @@ -198,6 +198,15 @@ func addGeoMultiPolygonToCluster(uid uint64, polygons [][][][]float64) { } const testSchema = ` +type Person { + name: string + pet: Animal +} + +type Animal { + name: string +} + name : string @index(term, exact, trigram) @count @lang . alias : string @index(exact, term, fulltext) . dob : dateTime @index(year) . diff --git a/query/query.go b/query/query.go index 2e0591a1581..36bf8a16fb9 100644 --- a/query/query.go +++ b/query/query.go @@ -2706,13 +2706,13 @@ func (e *InternalError) Error() string { return "pb.error: " + e.err.Error() } -// TODO: This looks unnecessary. -type ExecuteResult struct { +type ExecutionResult struct { Subgraphs []*SubGraph SchemaNode []*api.SchemaNode + Types []*pb.TypeUpdate } -func (req *QueryRequest) Process(ctx context.Context) (er ExecuteResult, err error) { +func (req *QueryRequest) Process(ctx context.Context) (er ExecutionResult, err error) { err = req.ProcessQuery(ctx) if err != nil { return er, err @@ -2723,6 +2723,9 @@ func (req *QueryRequest) Process(ctx context.Context) (er ExecuteResult, err err if er.SchemaNode, err = worker.GetSchemaOverNetwork(ctx, req.GqlQuery.Schema); err != nil { return er, x.Wrapf(&InternalError{err: err}, "error while fetching schema") } + if er.Types, err = worker.GetTypes(ctx, req.GqlQuery.Schema); err != nil { + return er, x.Wrapf(&InternalError{err: err}, "error while fetching types") + } } return er, nil } diff --git a/query/query3_test.go b/query/query3_test.go index 3bdbe2b741c..ef45be99d22 100644 --- a/query/query3_test.go +++ b/query/query3_test.go @@ -1974,3 +1974,26 @@ func TestMaxPredicateSize(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "Predicate name length cannot be bigger than 2^16") } + +func TestQueryUnknownType(t *testing.T) { + query := `schema(type: UnknownType) {}` + js := processQueryNoErr(t, query) + require.JSONEq(t, `{"data": {}}`, js) +} + +func TestQuerySingleType(t *testing.T) { + query := `schema(type: Person) {}` + js := processQueryNoErr(t, query) + require.JSONEq(t, `{"data": {"types":[{"name":"Person", + "fields":[{"name":"name", "type":"string"}, {"name":"pet", "type":"Animal"}]}]}}`, + js) +} + +func TestQueryMultipleTypes(t *testing.T) { + query := `schema(type: [Person, Animal]) {}` + js := processQueryNoErr(t, query) + require.JSONEq(t, `{"data": {"types":[{"name":"Animal", + "fields":[{"name":"name", "type":"string"}]}, + {"name":"Person", "fields":[{"name":"name", "type": "string"}, + {"name":"pet", "type":"Animal"}]}]}}`, js) +} diff --git a/schema/parse_test.go b/schema/parse_test.go index d1b01f60042..d998114fd29 100644 --- a/schema/parse_test.go +++ b/schema/parse_test.go @@ -407,7 +407,31 @@ func TestParseSingleType(t *testing.T) { }, }, }, result.Types[0]) +} +func TestParseBaseTypesCaseInsensitive(t *testing.T) { + reset() + result, err := Parse(` + type Person { + Name: string + LastName: String + } + `) + require.NoError(t, err) + require.Equal(t, 1, len(result.Types)) + require.Equal(t, &pb.TypeUpdate{ + TypeName: "Person", + Fields: []*pb.SchemaUpdate{ + &pb.SchemaUpdate{ + Predicate: "Name", + ValueType: pb.Posting_STRING, + }, + &pb.SchemaUpdate{ + Predicate: "LastName", + ValueType: pb.Posting_STRING, + }, + }, + }, result.Types[0]) } func TestParseCombinedSchemasAndTypes(t *testing.T) { diff --git a/schema/schema.go b/schema/schema.go index 0ed6f8e0e91..76a252bcf35 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -38,6 +38,7 @@ var ( func (s *state) init() { s.predicate = make(map[string]*pb.SchemaUpdate) + s.types = make(map[string]*pb.TypeUpdate) s.elog = trace.NewEventLog("Dgraph", "Schema") } @@ -45,6 +46,7 @@ type state struct { sync.RWMutex // Map containing predicate to type information. predicate map[string]*pb.SchemaUpdate + types map[string]*pb.TypeUpdate elog trace.EventLog } @@ -60,6 +62,10 @@ func (s *state) DeleteAll() { for pred := range s.predicate { delete(s.predicate, pred) } + + for typ := range s.types { + delete(s.types, typ) + } } // Delete updates the schema in memory and disk @@ -68,13 +74,36 @@ func (s *state) Delete(attr string) error { defer s.Unlock() glog.Infof("Deleting schema for predicate: [%s]", attr) - delete(s.predicate, attr) txn := pstore.NewTransactionAt(1, true) if err := txn.Delete(x.SchemaKey(attr)); err != nil { return err } // Delete is called rarely so sync write should be fine. - return txn.CommitAt(1, nil) + if err := txn.CommitAt(1, nil); err != nil { + return err + } + + delete(s.predicate, attr) + return nil +} + +// DeleteType updates the schema in memory and disk +func (s *state) DeleteType(typeName string) error { + s.Lock() + defer s.Unlock() + + glog.Infof("Deleting type definition for type: [%s]", typeName) + txn := pstore.NewTransactionAt(1, true) + if err := txn.Delete(x.TypeKey(typeName)); err != nil { + return err + } + // Delete is called rarely so sync write should be fine. + if err := txn.CommitAt(1, nil); err != nil { + return err + } + + delete(s.types, typeName) + return nil } func logUpdate(schema pb.SchemaUpdate, pred string) string { @@ -86,9 +115,12 @@ func logUpdate(schema pb.SchemaUpdate, pred string) string { pred, typ, schema.Tokenizer, schema.Directive, schema.Count) } -// Set sets the schema for given predicate in memory -// schema mutations must flow through update function, which are -// synced to db +func logTypeUpdate(typ pb.TypeUpdate, typeName string) string { + return fmt.Sprintf("Setting type definition for type %s: %v\n", typeName, typ) +} + +// Set sets the schema for the given predicate in memory. +// Schema mutations must flow through the update function, which are synced to the db. func (s *state) Set(pred string, schema pb.SchemaUpdate) { s.Lock() defer s.Unlock() @@ -96,7 +128,16 @@ func (s *state) Set(pred string, schema pb.SchemaUpdate) { s.elog.Printf(logUpdate(schema, pred)) } -// Get gets the schema for given predicate +// SetType sets the type for the given predicate in memory. +// schema mutations must flow through the update function, which are synced to the db. +func (s *state) SetType(typeName string, typ pb.TypeUpdate) { + s.Lock() + defer s.Unlock() + s.types[typeName] = &typ + s.elog.Printf(logTypeUpdate(typ, typeName)) +} + +// Get gets the schema for the given predicate. func (s *state) Get(pred string) (pb.SchemaUpdate, bool) { s.RLock() defer s.RUnlock() @@ -107,6 +148,17 @@ func (s *state) Get(pred string) (pb.SchemaUpdate, bool) { return *schema, true } +// GetType gets the type definition for the given type name. +func (s *state) GetType(typeName string) (pb.TypeUpdate, bool) { + s.RLock() + defer s.RUnlock() + typ, has := s.types[typeName] + if !has { + return pb.TypeUpdate{}, false + } + return *typ, true +} + // TypeOf returns the schema type of predicate func (s *state) TypeOf(pred string) (types.TypeID, error) { s.RLock() @@ -151,6 +203,17 @@ func (s *state) Predicates() []string { return out } +// Types returns the list of types. +func (s *state) Types() []string { + s.RLock() + defer s.RUnlock() + var out []string + for k := range s.types { + out = append(out, k) + } + return out +} + // Tokenizer returns the tokenizer for given predicate func (s *state) Tokenizer(pred string) []tok.Tokenizer { s.RLock() @@ -270,6 +333,16 @@ func Load(predicate string) error { // LoadFromDb reads schema information from db and stores it in memory func LoadFromDb() error { + if err := LoadSchemaFromDb(); err != nil { + return err + } + if err := LoadTypesFromDb(); err != nil { + return err + } + return nil +} + +func LoadSchemaFromDb() error { prefix := x.SchemaPrefix() txn := pstore.NewTransactionAt(1, false) defer txn.Discard() @@ -303,6 +376,40 @@ func LoadFromDb() error { return nil } +func LoadTypesFromDb() error { + prefix := x.TypePrefix() + txn := pstore.NewTransactionAt(1, false) + defer txn.Discard() + itr := txn.NewIterator(badger.DefaultIteratorOptions) // Need values, reversed=false. + defer itr.Close() + + for itr.Seek(prefix); itr.Valid(); itr.Next() { + item := itr.Item() + key := item.Key() + if !bytes.HasPrefix(key, prefix) { + break + } + pk := x.Parse(key) + if pk == nil { + continue + } + attr := pk.Attr + var t pb.TypeUpdate + err := item.Value(func(val []byte) error { + if len(val) == 0 { + t = pb.TypeUpdate{TypeName: attr} + } + x.Checkf(t.Unmarshal(val), "Error while loading types from db") + State().SetType(attr, t) + return nil + }) + if err != nil { + return err + } + } + return nil +} + func InitialSchema() []*pb.SchemaUpdate { var initialSchema []*pb.SchemaUpdate diff --git a/systest/mutations_test.go b/systest/mutations_test.go index 7ac3aefcb0d..1e40899fe71 100644 --- a/systest/mutations_test.go +++ b/systest/mutations_test.go @@ -677,17 +677,8 @@ func SchemaAfterDeleteNode(t *testing.T, c *dgo.Dgraph) { require.NoError(t, err) michael := assigned.Uids["michael"] - sortSchema := func(schema []*api.SchemaNode) { - sort.Slice(schema, func(i, j int) bool { - return schema[i].Predicate < schema[j].Predicate - }) - } - resp, err := c.NewTxn().Query(ctx, `schema{}`) require.NoError(t, err) - sortSchema(resp.Schema) - b, err := json.Marshal(resp.Schema) - require.NoError(t, err) z.CompareJSON(t, asJson(`[`+ `{"predicate":"_predicate_","type":"string","list":true},`+ x.AclPredicates+","+ @@ -695,7 +686,7 @@ func SchemaAfterDeleteNode(t *testing.T, c *dgo.Dgraph) { `{"predicate":"married","type":"bool"},`+ `{"predicate":"name","type":"default"},`+ `{"predicate":"type","type":"string","index":true, "tokenizer":["exact"]}]`), - asJson(string(b))) + string(resp.Json)) require.NoError(t, c.Alter(ctx, &api.Operation{DropAttr: "married"})) @@ -710,16 +701,13 @@ func SchemaAfterDeleteNode(t *testing.T, c *dgo.Dgraph) { resp, err = c.NewTxn().Query(ctx, `schema{}`) require.NoError(t, err) - sortSchema(resp.Schema) - b, err = json.Marshal(resp.Schema) - require.NoError(t, err) z.CompareJSON(t, asJson(`[`+ x.AclPredicates+","+ `{"predicate":"_predicate_","type":"string","list":true},`+ `{"predicate":"friend","type":"uid","list":true},`+ `{"predicate":"name","type":"default"},`+ `{"predicate":"type","type":"string","index":true, "tokenizer":["exact"]}]`), - asJson(string(b))) + string(resp.Json)) } func asJson(schema string) string { diff --git a/worker/draft.go b/worker/draft.go index 0bfed7a2455..09e9b267f6c 100644 --- a/worker/draft.go +++ b/worker/draft.go @@ -195,8 +195,8 @@ func (n *node) applyMutations(ctx context.Context, proposal *pb.Proposal) (rerr } startTs := proposal.Mutations.StartTs - if len(proposal.Mutations.Schema) > 0 { - span.Annotatef(nil, "Applying schema") + if len(proposal.Mutations.Schema) > 0 || len(proposal.Mutations.Types) > 0 { + span.Annotatef(nil, "Applying schema and types") for _, supdate := range proposal.Mutations.Schema { // We should not need to check for predicate move here. if err := detectPendingTxns(supdate.Predicate); err != nil { @@ -206,6 +206,13 @@ func (n *node) applyMutations(ctx context.Context, proposal *pb.Proposal) (rerr return err } } + + for _, tupdate := range proposal.Mutations.Types { + if err := runTypeMutation(ctx, tupdate, startTs); err != nil { + return err + } + } + return nil } diff --git a/worker/mutation.go b/worker/mutation.go index 31dc29f1d92..9fed5521e2c 100644 --- a/worker/mutation.go +++ b/worker/mutation.go @@ -120,8 +120,8 @@ func runSchemaMutationHelper(ctx context.Context, update *pb.SchemaUpdate, start } old, _ := schema.State().Get(update.Predicate) current := *update - // Sets only in memory, we will update it on disk only after schema mutations are successful and - // written to disk. + // Sets only in memory, we will update it on disk only after schema mutations + // are successful and written to disk. schema.State().Set(update.Predicate, current) // Once we remove index or reverse edges from schema, even though the values @@ -176,6 +176,30 @@ func updateSchemaType(attr string, typ types.TypeID, index uint64) { updateSchema(attr, s) } +func runTypeMutation(ctx context.Context, update *pb.TypeUpdate, startTs uint64) error { + if err := checkType(update); err != nil { + return err + } + current := *update + + schema.State().SetType(update.TypeName, current) + return updateType(update.TypeName, *update) +} + +// We commit schema to disk in blocking way, should be ok because this happens +// only during schema mutations or we see a new predicate. +func updateType(typeName string, t pb.TypeUpdate) error { + schema.State().SetType(typeName, t) + txn := pstore.NewTransactionAt(1, true) + defer txn.Discard() + data, err := t.Marshal() + x.Check(err) + if err := txn.SetWithMeta(x.TypeKey(typeName), data, posting.BitSchemaPosting); err != nil { + return err + } + return txn.CommitAt(1, nil) +} + func hasEdges(attr string, startTs uint64) bool { pk := x.ParsedKey{Attr: attr} iterOpt := badger.DefaultIteratorOptions @@ -200,7 +224,6 @@ func hasEdges(attr string, startTs uint64) bool { } return false } - func checkSchema(s *pb.SchemaUpdate) error { if len(s.Predicate) == 0 { return x.Errorf("No predicate specified in schema mutation") @@ -263,6 +286,32 @@ func checkSchema(s *pb.SchemaUpdate) error { return nil } +func checkType(t *pb.TypeUpdate) error { + if len(t.TypeName) == 0 { + return x.Errorf("Type name must be specified in type update") + } + + for _, field := range t.Fields { + if len(field.Predicate) == 0 { + return x.Errorf("Field in type definition must have a name") + } + + if field.ValueType == pb.Posting_OBJECT && len(field.ObjectTypeName) == 0 { + return x.Errorf("Field with value type OBJECT must specify the name of the object type") + } + + if field.Directive != pb.SchemaUpdate_NONE { + return x.Errorf("Field in type definition cannot have a directive") + } + + if len(field.Tokenizer) > 0 { + return x.Errorf("Field in type definition cannot have tokenizers") + } + } + + return nil +} + // 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 { @@ -404,6 +453,7 @@ func populateMutationMap(src *pb.Mutations) map[uint32]*pb.Mutations { } mu.Edges = append(mu.Edges, edge) } + for _, schema := range src.Schema { gid := groups().BelongsTo(schema.Predicate) mu := mm[gid] @@ -413,6 +463,7 @@ func populateMutationMap(src *pb.Mutations) map[uint32]*pb.Mutations { } mu.Schema = append(mu.Schema, schema) } + if src.DropAll { for _, gid := range groups().KnownGroups() { mu := mm[gid] @@ -423,6 +474,19 @@ func populateMutationMap(src *pb.Mutations) map[uint32]*pb.Mutations { mu.DropAll = true } } + + // Type definitions are sent to all groups. + if len(src.Types) > 0 { + for _, gid := range groups().KnownGroups() { + mu := mm[gid] + if mu == nil { + mu = &pb.Mutations{GroupId: gid} + mm[gid] = mu + } + mu.Types = src.Types + } + } + return mm } diff --git a/worker/proposal.go b/worker/proposal.go index 613ef821884..85220e08359 100644 --- a/worker/proposal.go +++ b/worker/proposal.go @@ -165,6 +165,11 @@ func (n *node) proposeAndWait(ctx context.Context, proposal *pb.Proposal) (perr } noTimeout = true } + for _, typ := range proposal.Mutations.Types { + if err := checkType(typ); err != nil { + return err + } + } } // Let's keep the same key, so multiple retries of the same proposal would diff --git a/worker/schema.go b/worker/schema.go index 9e6b06e9f6e..7e22e6baf94 100644 --- a/worker/schema.go +++ b/worker/schema.go @@ -172,6 +172,10 @@ func GetSchemaOverNetwork(ctx context.Context, schema *pb.SchemaRequest) ([]*api return nil, err } + if len(schema.Predicates) == 0 && len(schema.Types) > 0 { + return nil, nil + } + // Map of groupd id => Predicates for that group. schemaMap := make(map[uint32]*pb.SchemaRequest) addToSchemaMap(schemaMap, schema) @@ -214,3 +218,29 @@ func (w *grpcWorker) Schema(ctx context.Context, s *pb.SchemaRequest) (*pb.Schem } return getSchema(ctx, s) } + +// GetTypes processes the type requests and retrieves the desired types. +func GetTypes(ctx context.Context, req *pb.SchemaRequest) ([]*pb.TypeUpdate, error) { + if len(req.Types) == 0 && len(req.Predicates) > 0 { + return nil, nil + } + + var typeNames []string + var out []*pb.TypeUpdate + + if len(req.Types) == 0 { + typeNames = schema.State().Types() + } else { + typeNames = req.Types + } + + for _, name := range typeNames { + typeUpdate, found := schema.State().GetType(name) + if !found { + continue + } + out = append(out, &typeUpdate) + } + + return out, nil +} diff --git a/x/keys.go b/x/keys.go index ae0c072e904..199e80ebce7 100644 --- a/x/keys.go +++ b/x/keys.go @@ -35,6 +35,7 @@ const ( // keys of same attributes are located together defaultPrefix = byte(0x00) byteSchema = byte(0x01) + byteType = byte(0x02) ) func writeAttr(buf []byte, attr string) []byte { @@ -47,9 +48,8 @@ func writeAttr(buf []byte, attr string) []byte { return rest[len(attr):] } -// SchemaKey returns schema key for given attribute, -// schema keys are stored separately with unique prefix, -// since we need to iterate over all schema keys +// SchemaKey returns schema key for given attribute. Schema keys are stored +// separately with unique prefix, since we need to iterate over all schema keys. func SchemaKey(attr string) []byte { buf := make([]byte, 1+2+len(attr)) buf[0] = byteSchema @@ -59,6 +59,17 @@ func SchemaKey(attr string) []byte { return buf } +// TypeKey returns type key for given type name. Type keys are stored separately +// with unique prefix, since we need to iterate over all type keys. +func TypeKey(typeName string) []byte { + buf := make([]byte, 1+2+len(typeName)) + buf[0] = byteType + rest := buf[1:] + + writeAttr(rest, typeName) + return buf +} + func DataKey(attr string, uid uint64) []byte { buf := make([]byte, 2+len(attr)+2+8) buf[0] = defaultPrefix @@ -125,27 +136,31 @@ type ParsedKey struct { } func (p ParsedKey) IsData() bool { - return p.byteType == ByteData + return p.bytePrefix == defaultPrefix && p.byteType == ByteData } func (p ParsedKey) IsReverse() bool { - return p.byteType == ByteReverse + return p.bytePrefix == defaultPrefix && p.byteType == ByteReverse } func (p ParsedKey) IsCount() bool { - return p.byteType == ByteCount || - p.byteType == ByteCountRev + return p.bytePrefix == defaultPrefix && (p.byteType == ByteCount || + p.byteType == ByteCountRev) } func (p ParsedKey) IsIndex() bool { - return p.byteType == ByteIndex + return p.bytePrefix == defaultPrefix && p.byteType == ByteIndex } func (p ParsedKey) IsSchema() bool { return p.bytePrefix == byteSchema } -func (p ParsedKey) IsType(typ byte) bool { +func (p ParsedKey) IsType() bool { + return p.bytePrefix == byteType +} + +func (p ParsedKey) IsOfType(typ byte) bool { switch typ { case ByteCount, ByteCountRev: return p.IsCount() @@ -186,6 +201,12 @@ func (p ParsedKey) SkipSchema() []byte { return buf[:] } +func (p ParsedKey) SkipType() []byte { + var buf [1]byte + buf[0] = byteType + 1 + return buf[:] +} + // DataPrefix returns the prefix for data keys. func (p ParsedKey) DataPrefix() []byte { buf := make([]byte, 2+len(p.Attr)+2) @@ -241,6 +262,13 @@ func SchemaPrefix() []byte { return buf[:] } +// TypePrefix returns the prefix for Schema keys. +func TypePrefix() []byte { + var buf [1]byte + buf[0] = byteType + return buf[:] +} + // PredicatePrefix returns the prefix for all keys belonging // to this predicate except schema key. func PredicatePrefix(predicate string) []byte { @@ -264,7 +292,7 @@ func Parse(key []byte) *ParsedKey { k = k[sz:] switch p.bytePrefix { - case byteSchema: + case byteSchema, byteType: return p default: }