diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a5a35fba4c..b7f59c2314 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -77,7 +77,11 @@ jobs: - 4222:4222 env: NATS_EXTRA_ARGS: -js + steps: + - name: Start Pulsar standalone container + run: docker run -d -p 6650:6650 -p 8080:8080 apachepulsar/pulsar:4.0.0 bin/pulsar standalone + - name: Set up Go 1.x uses: actions/setup-go@v5 with: diff --git a/Dockerfile b/Dockerfile index 57feea2da7..bded35d1f9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ RUN chmod +x /bin/numaflow-rs #################################################################################################### # Rust binary #################################################################################################### -FROM lukemathwalker/cargo-chef:latest-rust-1.81 AS chef +FROM lukemathwalker/cargo-chef:latest-rust-1.82 AS chef ARG TARGETPLATFORM WORKDIR /numaflow RUN apt-get update && apt-get install -y protobuf-compiler diff --git a/Makefile b/Makefile index 450f9dc491..aab918c933 100644 --- a/Makefile +++ b/Makefile @@ -296,11 +296,11 @@ endif .PHONY: docs docs: /usr/local/bin/mkdocs docs-linkcheck - mkdocs build + $(PYTHON) -m mkdocs build .PHONY: docs-serve docs-serve: docs - mkdocs serve + $(PYTHON) -m mkdocs serve .PHONY: docs-linkcheck docs-linkcheck: /usr/local/bin/lychee diff --git a/api/json-schema/schema.json b/api/json-schema/schema.json index ffc4bbcfee..84ed58ed90 100644 --- a/api/json-schema/schema.json +++ b/api/json-schema/schema.json @@ -21651,6 +21651,48 @@ }, "type": "object" }, + "io.numaproj.numaflow.v1alpha1.PulsarAuth": { + "description": "PulsarAuth defines how to authenticate with Pulsar", + "properties": { + "token": { + "$ref": "#/definitions/io.k8s.api.core.v1.SecretKeySelector", + "description": "JWT Token auth" + } + }, + "type": "object" + }, + "io.numaproj.numaflow.v1alpha1.PulsarSource": { + "properties": { + "auth": { + "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.PulsarAuth", + "description": "Auth information" + }, + "consumerName": { + "type": "string" + }, + "maxUnack": { + "description": "Maximum number of messages that are in not yet acked state. Once this limit is crossed, futher read requests will return empty list.", + "format": "int64", + "type": "integer" + }, + "serverAddr": { + "type": "string" + }, + "subscriptionName": { + "type": "string" + }, + "topic": { + "type": "string" + } + }, + "required": [ + "serverAddr", + "topic", + "consumerName", + "subscriptionName" + ], + "type": "object" + }, "io.numaproj.numaflow.v1alpha1.RedisBufferService": { "properties": { "external": { @@ -22096,6 +22138,9 @@ "nats": { "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.NatsSource" }, + "pulsar": { + "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.PulsarSource" + }, "serving": { "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.ServingSource" }, diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index afb3bb8b07..19c65fe5cf 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -21637,6 +21637,48 @@ } } }, + "io.numaproj.numaflow.v1alpha1.PulsarAuth": { + "description": "PulsarAuth defines how to authenticate with Pulsar", + "type": "object", + "properties": { + "token": { + "description": "JWT Token auth", + "$ref": "#/definitions/io.k8s.api.core.v1.SecretKeySelector" + } + } + }, + "io.numaproj.numaflow.v1alpha1.PulsarSource": { + "type": "object", + "required": [ + "serverAddr", + "topic", + "consumerName", + "subscriptionName" + ], + "properties": { + "auth": { + "description": "Auth information", + "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.PulsarAuth" + }, + "consumerName": { + "type": "string" + }, + "maxUnack": { + "description": "Maximum number of messages that are in not yet acked state. Once this limit is crossed, futher read requests will return empty list.", + "type": "integer", + "format": "int64" + }, + "serverAddr": { + "type": "string" + }, + "subscriptionName": { + "type": "string" + }, + "topic": { + "type": "string" + } + } + }, "io.numaproj.numaflow.v1alpha1.RedisBufferService": { "type": "object", "properties": { @@ -22083,6 +22125,9 @@ "nats": { "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.NatsSource" }, + "pulsar": { + "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.PulsarSource" + }, "serving": { "$ref": "#/definitions/io.numaproj.numaflow.v1alpha1.ServingSource" }, diff --git a/config/base/crds/full/numaflow.numaproj.io_monovertices.yaml b/config/base/crds/full/numaflow.numaproj.io_monovertices.yaml index 79ffec3919..a9ff56ca3e 100644 --- a/config/base/crds/full/numaflow.numaproj.io_monovertices.yaml +++ b/config/base/crds/full/numaflow.numaproj.io_monovertices.yaml @@ -4992,6 +4992,41 @@ spec: - subject - url type: object + pulsar: + properties: + auth: + properties: + token: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + consumerName: + type: string + maxUnack: + format: int32 + type: integer + serverAddr: + type: string + subscriptionName: + type: string + topic: + type: string + required: + - consumerName + - serverAddr + - subscriptionName + - topic + type: object serving: properties: auth: diff --git a/config/base/crds/full/numaflow.numaproj.io_pipelines.yaml b/config/base/crds/full/numaflow.numaproj.io_pipelines.yaml index d035799a96..3e06abecea 100644 --- a/config/base/crds/full/numaflow.numaproj.io_pipelines.yaml +++ b/config/base/crds/full/numaflow.numaproj.io_pipelines.yaml @@ -9676,6 +9676,41 @@ spec: - subject - url type: object + pulsar: + properties: + auth: + properties: + token: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + consumerName: + type: string + maxUnack: + format: int32 + type: integer + serverAddr: + type: string + subscriptionName: + type: string + topic: + type: string + required: + - consumerName + - serverAddr + - subscriptionName + - topic + type: object serving: properties: auth: diff --git a/config/base/crds/full/numaflow.numaproj.io_vertices.yaml b/config/base/crds/full/numaflow.numaproj.io_vertices.yaml index 0dfad151d6..5f80efaf57 100644 --- a/config/base/crds/full/numaflow.numaproj.io_vertices.yaml +++ b/config/base/crds/full/numaflow.numaproj.io_vertices.yaml @@ -4460,6 +4460,41 @@ spec: - subject - url type: object + pulsar: + properties: + auth: + properties: + token: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + consumerName: + type: string + maxUnack: + format: int32 + type: integer + serverAddr: + type: string + subscriptionName: + type: string + topic: + type: string + required: + - consumerName + - serverAddr + - subscriptionName + - topic + type: object serving: properties: auth: diff --git a/config/install.yaml b/config/install.yaml index d6332dc53f..6e3551c059 100644 --- a/config/install.yaml +++ b/config/install.yaml @@ -8179,6 +8179,41 @@ spec: - subject - url type: object + pulsar: + properties: + auth: + properties: + token: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + consumerName: + type: string + maxUnack: + format: int32 + type: integer + serverAddr: + type: string + subscriptionName: + type: string + topic: + type: string + required: + - consumerName + - serverAddr + - subscriptionName + - topic + type: object serving: properties: auth: @@ -19414,6 +19449,41 @@ spec: - subject - url type: object + pulsar: + properties: + auth: + properties: + token: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + consumerName: + type: string + maxUnack: + format: int32 + type: integer + serverAddr: + type: string + subscriptionName: + type: string + topic: + type: string + required: + - consumerName + - serverAddr + - subscriptionName + - topic + type: object serving: properties: auth: @@ -25824,6 +25894,41 @@ spec: - subject - url type: object + pulsar: + properties: + auth: + properties: + token: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + consumerName: + type: string + maxUnack: + format: int32 + type: integer + serverAddr: + type: string + subscriptionName: + type: string + topic: + type: string + required: + - consumerName + - serverAddr + - subscriptionName + - topic + type: object serving: properties: auth: diff --git a/config/namespace-install.yaml b/config/namespace-install.yaml index e2769284de..12821ec38d 100644 --- a/config/namespace-install.yaml +++ b/config/namespace-install.yaml @@ -8179,6 +8179,41 @@ spec: - subject - url type: object + pulsar: + properties: + auth: + properties: + token: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + consumerName: + type: string + maxUnack: + format: int32 + type: integer + serverAddr: + type: string + subscriptionName: + type: string + topic: + type: string + required: + - consumerName + - serverAddr + - subscriptionName + - topic + type: object serving: properties: auth: @@ -19414,6 +19449,41 @@ spec: - subject - url type: object + pulsar: + properties: + auth: + properties: + token: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + consumerName: + type: string + maxUnack: + format: int32 + type: integer + serverAddr: + type: string + subscriptionName: + type: string + topic: + type: string + required: + - consumerName + - serverAddr + - subscriptionName + - topic + type: object serving: properties: auth: @@ -25824,6 +25894,41 @@ spec: - subject - url type: object + pulsar: + properties: + auth: + properties: + token: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + consumerName: + type: string + maxUnack: + format: int32 + type: integer + serverAddr: + type: string + subscriptionName: + type: string + topic: + type: string + required: + - consumerName + - serverAddr + - subscriptionName + - topic + type: object serving: properties: auth: diff --git a/docs/APIs.md b/docs/APIs.md index 57c594c67b..bcda2eb8d4 100644 --- a/docs/APIs.md +++ b/docs/APIs.md @@ -8436,6 +8436,206 @@ having succeeded. Defaults to 3. Minimum value is 1. +

+ +PulsarAuth +

+ +

+ +(Appears on: +PulsarSource) +

+ +

+ +

+ +PulsarAuth defines how to authenticate with Pulsar +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +Field + + +Description +
+ +token
+ +Kubernetes core/v1.SecretKeySelector +
+ +(Optional) +

+ +JWT Token auth +

+ +
+ +

+ +PulsarSource +

+ +

+ +(Appears on: +Source) +

+ +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +Field + + +Description +
+ +serverAddr
string +
+ +
+ +topic
string +
+ +
+ +consumerName
string +
+ +
+ +subscriptionName
string +
+ +
+ +maxUnack
uint32 +
+ +

+ +Maximum number of messages that are in not yet acked state. Once this +limit is crossed, futher read requests will return empty list. +

+ +
+ +auth
+ PulsarAuth + +
+ +(Optional) +

+ +Auth information +

+ +
+

RedisBufferService @@ -10453,6 +10653,22 @@ JetStreamSource + + + + +pulsar
+ PulsarSource + + + + + +(Optional) + + + + diff --git a/docs/user-guide/sources/kafka.md b/docs/user-guide/sources/kafka.md index 3fdd9b2c4f..f0e9f61c3a 100644 --- a/docs/user-guide/sources/kafka.md +++ b/docs/user-guide/sources/kafka.md @@ -18,7 +18,7 @@ spec: offsets: initial: -2 # -2 for sarama.OffsetOldest, -1 for sarama.OffsetNewest. Default to sarama.OffsetNewest. tls: # Optional. - insecureSkipVerify: # Optional, where to skip TLS verification. Default to false. + insecureSkipVerify: # Optional, whether to skip TLS verification. Default to false. caCertSecret: # Optional, a secret reference, which contains the CA Cert. name: my-ca-cert key: my-ca-cert-key diff --git a/docs/user-guide/sources/nats.md b/docs/user-guide/sources/nats.md index 17ef120ffc..c57e26fb54 100644 --- a/docs/user-guide/sources/nats.md +++ b/docs/user-guide/sources/nats.md @@ -12,7 +12,7 @@ spec: subject: my-subject queue: my-queue # Queue subscription, see https://docs.nats.io/using-nats/developer/receiving/queues tls: # Optional. - insecureSkipVerify: # Optional, where to skip TLS verification. Default to false. + insecureSkipVerify: # Optional, whether to skip TLS verification. Default to false. caCertSecret: # Optional, a secret reference, which contains the CA Cert. name: my-ca-cert key: my-ca-cert-key diff --git a/docs/user-guide/sources/pulsar.md b/docs/user-guide/sources/pulsar.md new file mode 100644 index 0000000000..ca932920c9 --- /dev/null +++ b/docs/user-guide/sources/pulsar.md @@ -0,0 +1,39 @@ +# Pulsar Source + +#### NOTE: 1.5 Feature, not available Numaflow version < 1.5 + +A `Pulsar` source is used to ingest the messages from a Pulsar topic. + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: pulsar +type: Opaque +data: + token: ZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKemRXSWlPaUowWlhOMExYVnpaWElpZlEuZkRTWFFOcEdBWUN4anN1QlZzSDRTM2VLOVlZdHpwejhfdkFZcUxwVHAybwo= + +--- +apiVersion: numaflow.numaproj.io/v1alpha1 +kind: Pipeline +metadata: + name: simple-pipeline +spec: + vertices: + - name: in + source: + pulsar: + serverAddr: "pulsar+ssl://borker.example.com:6651" + consumerName: my_consumer + topic: my_topic + subscriptionName: my_subscription + auth: # Optional + token: # Optional, pointing to a secret reference which contains the JWT Token. + name: pulsar + key: token +``` + +We have only tested the 4.0.x LTS version of Pulsar. Currently, the implementation only supports [JWT token](https://pulsar.apache.org/docs/4.0.x/security-jwt/) based authentication. If the `auth` field is not specified, Numaflow will connect to the Pulsar servers without authentication. + +More authentication mechanisms and the ability to customize Pulsar consumer will be added in the future. + diff --git a/mkdocs.yml b/mkdocs.yml index 68e1c6411c..205c6f705a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -51,6 +51,7 @@ nav: - user-guide/sources/generator.md - user-guide/sources/http.md - user-guide/sources/kafka.md + - user-guide/sources/pulsar.md - user-guide/sources/nats.md - user-guide/sources/user-defined-sources.md - Data Transformer: diff --git a/pkg/apis/numaflow/v1alpha1/generated.pb.go b/pkg/apis/numaflow/v1alpha1/generated.pb.go index cc34329198..0a90cd05d9 100644 --- a/pkg/apis/numaflow/v1alpha1/generated.pb.go +++ b/pkg/apis/numaflow/v1alpha1/generated.pb.go @@ -1758,10 +1758,66 @@ func (m *Probe) XXX_DiscardUnknown() { var xxx_messageInfo_Probe proto.InternalMessageInfo +func (m *PulsarAuth) Reset() { *m = PulsarAuth{} } +func (*PulsarAuth) ProtoMessage() {} +func (*PulsarAuth) Descriptor() ([]byte, []int) { + return fileDescriptor_9d0d1b17d3865563, []int{61} +} +func (m *PulsarAuth) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PulsarAuth) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *PulsarAuth) XXX_Merge(src proto.Message) { + xxx_messageInfo_PulsarAuth.Merge(m, src) +} +func (m *PulsarAuth) XXX_Size() int { + return m.Size() +} +func (m *PulsarAuth) XXX_DiscardUnknown() { + xxx_messageInfo_PulsarAuth.DiscardUnknown(m) +} + +var xxx_messageInfo_PulsarAuth proto.InternalMessageInfo + +func (m *PulsarSource) Reset() { *m = PulsarSource{} } +func (*PulsarSource) ProtoMessage() {} +func (*PulsarSource) Descriptor() ([]byte, []int) { + return fileDescriptor_9d0d1b17d3865563, []int{62} +} +func (m *PulsarSource) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PulsarSource) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *PulsarSource) XXX_Merge(src proto.Message) { + xxx_messageInfo_PulsarSource.Merge(m, src) +} +func (m *PulsarSource) XXX_Size() int { + return m.Size() +} +func (m *PulsarSource) XXX_DiscardUnknown() { + xxx_messageInfo_PulsarSource.DiscardUnknown(m) +} + +var xxx_messageInfo_PulsarSource proto.InternalMessageInfo + func (m *RedisBufferService) Reset() { *m = RedisBufferService{} } func (*RedisBufferService) ProtoMessage() {} func (*RedisBufferService) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{61} + return fileDescriptor_9d0d1b17d3865563, []int{63} } func (m *RedisBufferService) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1789,7 +1845,7 @@ var xxx_messageInfo_RedisBufferService proto.InternalMessageInfo func (m *RedisConfig) Reset() { *m = RedisConfig{} } func (*RedisConfig) ProtoMessage() {} func (*RedisConfig) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{62} + return fileDescriptor_9d0d1b17d3865563, []int{64} } func (m *RedisConfig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1817,7 +1873,7 @@ var xxx_messageInfo_RedisConfig proto.InternalMessageInfo func (m *RedisSettings) Reset() { *m = RedisSettings{} } func (*RedisSettings) ProtoMessage() {} func (*RedisSettings) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{63} + return fileDescriptor_9d0d1b17d3865563, []int{65} } func (m *RedisSettings) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1845,7 +1901,7 @@ var xxx_messageInfo_RedisSettings proto.InternalMessageInfo func (m *RetryStrategy) Reset() { *m = RetryStrategy{} } func (*RetryStrategy) ProtoMessage() {} func (*RetryStrategy) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{64} + return fileDescriptor_9d0d1b17d3865563, []int{66} } func (m *RetryStrategy) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1873,7 +1929,7 @@ var xxx_messageInfo_RetryStrategy proto.InternalMessageInfo func (m *RollingUpdateStrategy) Reset() { *m = RollingUpdateStrategy{} } func (*RollingUpdateStrategy) ProtoMessage() {} func (*RollingUpdateStrategy) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{65} + return fileDescriptor_9d0d1b17d3865563, []int{67} } func (m *RollingUpdateStrategy) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1901,7 +1957,7 @@ var xxx_messageInfo_RollingUpdateStrategy proto.InternalMessageInfo func (m *SASL) Reset() { *m = SASL{} } func (*SASL) ProtoMessage() {} func (*SASL) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{66} + return fileDescriptor_9d0d1b17d3865563, []int{68} } func (m *SASL) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1929,7 +1985,7 @@ var xxx_messageInfo_SASL proto.InternalMessageInfo func (m *SASLPlain) Reset() { *m = SASLPlain{} } func (*SASLPlain) ProtoMessage() {} func (*SASLPlain) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{67} + return fileDescriptor_9d0d1b17d3865563, []int{69} } func (m *SASLPlain) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1957,7 +2013,7 @@ var xxx_messageInfo_SASLPlain proto.InternalMessageInfo func (m *Scale) Reset() { *m = Scale{} } func (*Scale) ProtoMessage() {} func (*Scale) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{68} + return fileDescriptor_9d0d1b17d3865563, []int{70} } func (m *Scale) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1985,7 +2041,7 @@ var xxx_messageInfo_Scale proto.InternalMessageInfo func (m *ServingSource) Reset() { *m = ServingSource{} } func (*ServingSource) ProtoMessage() {} func (*ServingSource) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{69} + return fileDescriptor_9d0d1b17d3865563, []int{71} } func (m *ServingSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2013,7 +2069,7 @@ var xxx_messageInfo_ServingSource proto.InternalMessageInfo func (m *ServingStore) Reset() { *m = ServingStore{} } func (*ServingStore) ProtoMessage() {} func (*ServingStore) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{70} + return fileDescriptor_9d0d1b17d3865563, []int{72} } func (m *ServingStore) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2041,7 +2097,7 @@ var xxx_messageInfo_ServingStore proto.InternalMessageInfo func (m *SessionWindow) Reset() { *m = SessionWindow{} } func (*SessionWindow) ProtoMessage() {} func (*SessionWindow) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{71} + return fileDescriptor_9d0d1b17d3865563, []int{73} } func (m *SessionWindow) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2069,7 +2125,7 @@ var xxx_messageInfo_SessionWindow proto.InternalMessageInfo func (m *SideInput) Reset() { *m = SideInput{} } func (*SideInput) ProtoMessage() {} func (*SideInput) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{72} + return fileDescriptor_9d0d1b17d3865563, []int{74} } func (m *SideInput) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2097,7 +2153,7 @@ var xxx_messageInfo_SideInput proto.InternalMessageInfo func (m *SideInputTrigger) Reset() { *m = SideInputTrigger{} } func (*SideInputTrigger) ProtoMessage() {} func (*SideInputTrigger) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{73} + return fileDescriptor_9d0d1b17d3865563, []int{75} } func (m *SideInputTrigger) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2125,7 +2181,7 @@ var xxx_messageInfo_SideInputTrigger proto.InternalMessageInfo func (m *SideInputsManagerTemplate) Reset() { *m = SideInputsManagerTemplate{} } func (*SideInputsManagerTemplate) ProtoMessage() {} func (*SideInputsManagerTemplate) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{74} + return fileDescriptor_9d0d1b17d3865563, []int{76} } func (m *SideInputsManagerTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2153,7 +2209,7 @@ var xxx_messageInfo_SideInputsManagerTemplate proto.InternalMessageInfo func (m *Sink) Reset() { *m = Sink{} } func (*Sink) ProtoMessage() {} func (*Sink) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{75} + return fileDescriptor_9d0d1b17d3865563, []int{77} } func (m *Sink) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2181,7 +2237,7 @@ var xxx_messageInfo_Sink proto.InternalMessageInfo func (m *SlidingWindow) Reset() { *m = SlidingWindow{} } func (*SlidingWindow) ProtoMessage() {} func (*SlidingWindow) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{76} + return fileDescriptor_9d0d1b17d3865563, []int{78} } func (m *SlidingWindow) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2209,7 +2265,7 @@ var xxx_messageInfo_SlidingWindow proto.InternalMessageInfo func (m *Source) Reset() { *m = Source{} } func (*Source) ProtoMessage() {} func (*Source) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{77} + return fileDescriptor_9d0d1b17d3865563, []int{79} } func (m *Source) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2237,7 +2293,7 @@ var xxx_messageInfo_Source proto.InternalMessageInfo func (m *Status) Reset() { *m = Status{} } func (*Status) ProtoMessage() {} func (*Status) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{78} + return fileDescriptor_9d0d1b17d3865563, []int{80} } func (m *Status) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2265,7 +2321,7 @@ var xxx_messageInfo_Status proto.InternalMessageInfo func (m *TLS) Reset() { *m = TLS{} } func (*TLS) ProtoMessage() {} func (*TLS) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{79} + return fileDescriptor_9d0d1b17d3865563, []int{81} } func (m *TLS) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2293,7 +2349,7 @@ var xxx_messageInfo_TLS proto.InternalMessageInfo func (m *TagConditions) Reset() { *m = TagConditions{} } func (*TagConditions) ProtoMessage() {} func (*TagConditions) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{80} + return fileDescriptor_9d0d1b17d3865563, []int{82} } func (m *TagConditions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2321,7 +2377,7 @@ var xxx_messageInfo_TagConditions proto.InternalMessageInfo func (m *Templates) Reset() { *m = Templates{} } func (*Templates) ProtoMessage() {} func (*Templates) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{81} + return fileDescriptor_9d0d1b17d3865563, []int{83} } func (m *Templates) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2349,7 +2405,7 @@ var xxx_messageInfo_Templates proto.InternalMessageInfo func (m *Transformer) Reset() { *m = Transformer{} } func (*Transformer) ProtoMessage() {} func (*Transformer) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{82} + return fileDescriptor_9d0d1b17d3865563, []int{84} } func (m *Transformer) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2377,7 +2433,7 @@ var xxx_messageInfo_Transformer proto.InternalMessageInfo func (m *UDF) Reset() { *m = UDF{} } func (*UDF) ProtoMessage() {} func (*UDF) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{83} + return fileDescriptor_9d0d1b17d3865563, []int{85} } func (m *UDF) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2405,7 +2461,7 @@ var xxx_messageInfo_UDF proto.InternalMessageInfo func (m *UDSink) Reset() { *m = UDSink{} } func (*UDSink) ProtoMessage() {} func (*UDSink) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{84} + return fileDescriptor_9d0d1b17d3865563, []int{86} } func (m *UDSink) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2433,7 +2489,7 @@ var xxx_messageInfo_UDSink proto.InternalMessageInfo func (m *UDSource) Reset() { *m = UDSource{} } func (*UDSource) ProtoMessage() {} func (*UDSource) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{85} + return fileDescriptor_9d0d1b17d3865563, []int{87} } func (m *UDSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2461,7 +2517,7 @@ var xxx_messageInfo_UDSource proto.InternalMessageInfo func (m *UDTransformer) Reset() { *m = UDTransformer{} } func (*UDTransformer) ProtoMessage() {} func (*UDTransformer) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{86} + return fileDescriptor_9d0d1b17d3865563, []int{88} } func (m *UDTransformer) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2489,7 +2545,7 @@ var xxx_messageInfo_UDTransformer proto.InternalMessageInfo func (m *UpdateStrategy) Reset() { *m = UpdateStrategy{} } func (*UpdateStrategy) ProtoMessage() {} func (*UpdateStrategy) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{87} + return fileDescriptor_9d0d1b17d3865563, []int{89} } func (m *UpdateStrategy) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2517,7 +2573,7 @@ var xxx_messageInfo_UpdateStrategy proto.InternalMessageInfo func (m *Vertex) Reset() { *m = Vertex{} } func (*Vertex) ProtoMessage() {} func (*Vertex) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{88} + return fileDescriptor_9d0d1b17d3865563, []int{90} } func (m *Vertex) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2545,7 +2601,7 @@ var xxx_messageInfo_Vertex proto.InternalMessageInfo func (m *VertexInstance) Reset() { *m = VertexInstance{} } func (*VertexInstance) ProtoMessage() {} func (*VertexInstance) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{89} + return fileDescriptor_9d0d1b17d3865563, []int{91} } func (m *VertexInstance) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2573,7 +2629,7 @@ var xxx_messageInfo_VertexInstance proto.InternalMessageInfo func (m *VertexLimits) Reset() { *m = VertexLimits{} } func (*VertexLimits) ProtoMessage() {} func (*VertexLimits) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{90} + return fileDescriptor_9d0d1b17d3865563, []int{92} } func (m *VertexLimits) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2601,7 +2657,7 @@ var xxx_messageInfo_VertexLimits proto.InternalMessageInfo func (m *VertexList) Reset() { *m = VertexList{} } func (*VertexList) ProtoMessage() {} func (*VertexList) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{91} + return fileDescriptor_9d0d1b17d3865563, []int{93} } func (m *VertexList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2629,7 +2685,7 @@ var xxx_messageInfo_VertexList proto.InternalMessageInfo func (m *VertexSpec) Reset() { *m = VertexSpec{} } func (*VertexSpec) ProtoMessage() {} func (*VertexSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{92} + return fileDescriptor_9d0d1b17d3865563, []int{94} } func (m *VertexSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2657,7 +2713,7 @@ var xxx_messageInfo_VertexSpec proto.InternalMessageInfo func (m *VertexStatus) Reset() { *m = VertexStatus{} } func (*VertexStatus) ProtoMessage() {} func (*VertexStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{93} + return fileDescriptor_9d0d1b17d3865563, []int{95} } func (m *VertexStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2685,7 +2741,7 @@ var xxx_messageInfo_VertexStatus proto.InternalMessageInfo func (m *VertexTemplate) Reset() { *m = VertexTemplate{} } func (*VertexTemplate) ProtoMessage() {} func (*VertexTemplate) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{94} + return fileDescriptor_9d0d1b17d3865563, []int{96} } func (m *VertexTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2713,7 +2769,7 @@ var xxx_messageInfo_VertexTemplate proto.InternalMessageInfo func (m *Watermark) Reset() { *m = Watermark{} } func (*Watermark) ProtoMessage() {} func (*Watermark) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{95} + return fileDescriptor_9d0d1b17d3865563, []int{97} } func (m *Watermark) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2741,7 +2797,7 @@ var xxx_messageInfo_Watermark proto.InternalMessageInfo func (m *Window) Reset() { *m = Window{} } func (*Window) ProtoMessage() {} func (*Window) Descriptor() ([]byte, []int) { - return fileDescriptor_9d0d1b17d3865563, []int{96} + return fileDescriptor_9d0d1b17d3865563, []int{98} } func (m *Window) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2836,6 +2892,8 @@ func init() { proto.RegisterType((*PipelineSpec)(nil), "github.aaakk.us.kg.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.PipelineSpec") proto.RegisterType((*PipelineStatus)(nil), "github.aaakk.us.kg.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.PipelineStatus") proto.RegisterType((*Probe)(nil), "github.aaakk.us.kg.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.Probe") + proto.RegisterType((*PulsarAuth)(nil), "github.aaakk.us.kg.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.PulsarAuth") + proto.RegisterType((*PulsarSource)(nil), "github.aaakk.us.kg.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.PulsarSource") proto.RegisterType((*RedisBufferService)(nil), "github.aaakk.us.kg.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.RedisBufferService") proto.RegisterType((*RedisConfig)(nil), "github.aaakk.us.kg.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.RedisConfig") proto.RegisterType((*RedisSettings)(nil), "github.aaakk.us.kg.numaproj.numaflow.pkg.apis.numaflow.v1alpha1.RedisSettings") @@ -2880,518 +2938,526 @@ func init() { } var fileDescriptor_9d0d1b17d3865563 = []byte{ - // 8167 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x5d, 0x6c, 0x24, 0x57, - 0x76, 0x9e, 0xfa, 0x8f, 0xdd, 0x7d, 0x9a, 0x7f, 0xba, 0x33, 0x1a, 0x71, 0xb8, 0xa3, 0xe9, 0xd9, - 0x5a, 0xaf, 0x76, 0x1c, 0xdb, 0x64, 0x44, 0xaf, 0xb4, 0x5a, 0xdb, 0xbb, 0x12, 0x9b, 0x1c, 0x72, - 0xa8, 0x21, 0x67, 0xb8, 0xa7, 0xc9, 0x91, 0xd6, 0x8a, 0x57, 0x29, 0x56, 0x5d, 0x36, 0x4b, 0xac, - 0xae, 0xea, 0xad, 0xaa, 0xe6, 0x0c, 0xe5, 0x18, 0x6b, 0xef, 0x26, 0xd0, 0x06, 0x49, 0x90, 0xc0, - 0x4f, 0x06, 0x02, 0x27, 0x48, 0x10, 0xc0, 0x0f, 0x86, 0xf3, 0x60, 0x64, 0xf3, 0x10, 0x20, 0x3f, - 0x0e, 0x82, 0x64, 0xf3, 0xbf, 0x08, 0x02, 0x44, 0x79, 0x08, 0x91, 0x65, 0x90, 0x87, 0x04, 0x48, - 0xe0, 0xc4, 0x48, 0x9c, 0x0c, 0x8c, 0x38, 0xb8, 0x7f, 0xf5, 0xd7, 0xd5, 0x33, 0x64, 0x57, 0x73, - 0x34, 0x5a, 0xeb, 0xad, 0xea, 0x9e, 0x73, 0xbf, 0x73, 0xeb, 0xd6, 0xfd, 0x39, 0xf7, 0x9c, 0x73, - 0xef, 0x85, 0xf5, 0x8e, 0x15, 0x1c, 0xf4, 0xf7, 0x16, 0x0c, 0xb7, 0xbb, 0xe8, 0xf4, 0xbb, 0x7a, - 0xcf, 0x73, 0xdf, 0xe7, 0x0f, 0xfb, 0xb6, 0xfb, 0x60, 0xb1, 0x77, 0xd8, 0x59, 0xd4, 0x7b, 0x96, - 0x1f, 0xa5, 0x1c, 0xbd, 0xa2, 0xdb, 0xbd, 0x03, 0xfd, 0x95, 0xc5, 0x0e, 0x75, 0xa8, 0xa7, 0x07, - 0xd4, 0x5c, 0xe8, 0x79, 0x6e, 0xe0, 0x92, 0x2f, 0x45, 0x40, 0x0b, 0x0a, 0x68, 0x41, 0x65, 0x5b, - 0xe8, 0x1d, 0x76, 0x16, 0x18, 0x50, 0x94, 0xa2, 0x80, 0xe6, 0x7f, 0x2a, 0x56, 0x82, 0x8e, 0xdb, - 0x71, 0x17, 0x39, 0xde, 0x5e, 0x7f, 0x9f, 0xbf, 0xf1, 0x17, 0xfe, 0x24, 0xe4, 0xcc, 0x6b, 0x87, - 0xaf, 0xfb, 0x0b, 0x96, 0xcb, 0x8a, 0xb5, 0x68, 0xb8, 0x1e, 0x5d, 0x3c, 0x1a, 0x28, 0xcb, 0xfc, - 0x17, 0x23, 0x9e, 0xae, 0x6e, 0x1c, 0x58, 0x0e, 0xf5, 0x8e, 0xd5, 0xb7, 0x2c, 0x7a, 0xd4, 0x77, - 0xfb, 0x9e, 0x41, 0xcf, 0x95, 0xcb, 0x5f, 0xec, 0xd2, 0x40, 0xcf, 0x92, 0xb5, 0x38, 0x2c, 0x97, - 0xd7, 0x77, 0x02, 0xab, 0x3b, 0x28, 0xe6, 0xb5, 0x27, 0x65, 0xf0, 0x8d, 0x03, 0xda, 0xd5, 0x07, - 0xf2, 0xfd, 0xf4, 0xb0, 0x7c, 0xfd, 0xc0, 0xb2, 0x17, 0x2d, 0x27, 0xf0, 0x03, 0x2f, 0x9d, 0x49, - 0xfb, 0x1d, 0x80, 0x4b, 0xcb, 0x7b, 0x7e, 0xe0, 0xe9, 0x46, 0xb0, 0xed, 0x9a, 0x3b, 0xb4, 0xdb, - 0xb3, 0xf5, 0x80, 0x92, 0x43, 0xa8, 0xb1, 0x0f, 0x32, 0xf5, 0x40, 0x9f, 0x2b, 0xdc, 0x28, 0xdc, - 0x6c, 0x2c, 0x2d, 0x2f, 0x8c, 0xf8, 0x03, 0x17, 0xb6, 0x24, 0x50, 0x6b, 0xf2, 0xf4, 0xa4, 0x59, - 0x53, 0x6f, 0x18, 0x0a, 0x20, 0xbf, 0x56, 0x80, 0x49, 0xc7, 0x35, 0x69, 0x9b, 0xda, 0xd4, 0x08, - 0x5c, 0x6f, 0xae, 0x78, 0xa3, 0x74, 0xb3, 0xb1, 0xf4, 0x8d, 0x91, 0x25, 0x66, 0x7c, 0xd1, 0xc2, - 0xdd, 0x98, 0x80, 0x5b, 0x4e, 0xe0, 0x1d, 0xb7, 0x2e, 0x7f, 0xff, 0xa4, 0xf9, 0xdc, 0xe9, 0x49, - 0x73, 0x32, 0x4e, 0xc2, 0x44, 0x49, 0xc8, 0x2e, 0x34, 0x02, 0xd7, 0x66, 0x55, 0x66, 0xb9, 0x8e, - 0x3f, 0x57, 0xe2, 0x05, 0xbb, 0xbe, 0x20, 0xaa, 0x9a, 0x89, 0x5f, 0x60, 0x6d, 0x6c, 0xe1, 0xe8, - 0x95, 0x85, 0x9d, 0x90, 0xad, 0x75, 0x49, 0x02, 0x37, 0xa2, 0x34, 0x1f, 0xe3, 0x38, 0x84, 0xc2, - 0x8c, 0x4f, 0x8d, 0xbe, 0x67, 0x05, 0xc7, 0x2b, 0xae, 0x13, 0xd0, 0x87, 0xc1, 0x5c, 0x99, 0xd7, - 0xf2, 0xcb, 0x59, 0xd0, 0xdb, 0xae, 0xd9, 0x4e, 0x72, 0xb7, 0x2e, 0x9d, 0x9e, 0x34, 0x67, 0x52, - 0x89, 0x98, 0xc6, 0x24, 0x0e, 0xcc, 0x5a, 0x5d, 0xbd, 0x43, 0xb7, 0xfb, 0xb6, 0xdd, 0xa6, 0x86, - 0x47, 0x03, 0x7f, 0xae, 0xc2, 0x3f, 0xe1, 0x66, 0x96, 0x9c, 0x4d, 0xd7, 0xd0, 0xed, 0x7b, 0x7b, - 0xef, 0x53, 0x23, 0x40, 0xba, 0x4f, 0x3d, 0xea, 0x18, 0xb4, 0x35, 0x27, 0x3f, 0x66, 0x76, 0x23, - 0x85, 0x84, 0x03, 0xd8, 0x64, 0x1d, 0x9e, 0xef, 0x79, 0x96, 0xcb, 0x8b, 0x60, 0xeb, 0xbe, 0x7f, - 0x57, 0xef, 0xd2, 0xb9, 0x89, 0x1b, 0x85, 0x9b, 0xf5, 0xd6, 0x55, 0x09, 0xf3, 0xfc, 0x76, 0x9a, - 0x01, 0x07, 0xf3, 0x90, 0x9b, 0x50, 0x53, 0x89, 0x73, 0xd5, 0x1b, 0x85, 0x9b, 0x15, 0xd1, 0x76, - 0x54, 0x5e, 0x0c, 0xa9, 0x64, 0x0d, 0x6a, 0xfa, 0xfe, 0xbe, 0xe5, 0x30, 0xce, 0x1a, 0xaf, 0xc2, - 0x6b, 0x59, 0x9f, 0xb6, 0x2c, 0x79, 0x04, 0x8e, 0x7a, 0xc3, 0x30, 0x2f, 0x79, 0x0b, 0x88, 0x4f, - 0xbd, 0x23, 0xcb, 0xa0, 0xcb, 0x86, 0xe1, 0xf6, 0x9d, 0x80, 0x97, 0xbd, 0xce, 0xcb, 0x3e, 0x2f, - 0xcb, 0x4e, 0xda, 0x03, 0x1c, 0x98, 0x91, 0x8b, 0xbc, 0x09, 0xb3, 0xb2, 0xaf, 0x46, 0xb5, 0x00, - 0x1c, 0xe9, 0x32, 0xab, 0x48, 0x4c, 0xd1, 0x70, 0x80, 0x9b, 0x98, 0x70, 0x4d, 0xef, 0x07, 0x6e, - 0x97, 0x41, 0x26, 0x85, 0xee, 0xb8, 0x87, 0xd4, 0x99, 0x6b, 0xdc, 0x28, 0xdc, 0xac, 0xb5, 0x6e, - 0x9c, 0x9e, 0x34, 0xaf, 0x2d, 0x3f, 0x86, 0x0f, 0x1f, 0x8b, 0x42, 0xee, 0x41, 0xdd, 0x74, 0xfc, - 0x6d, 0xd7, 0xb6, 0x8c, 0xe3, 0xb9, 0x49, 0x5e, 0xc0, 0x57, 0xe4, 0xa7, 0xd6, 0x57, 0xef, 0xb6, - 0x05, 0xe1, 0xd1, 0x49, 0xf3, 0xda, 0xe0, 0x90, 0xba, 0x10, 0xd2, 0x31, 0xc2, 0x20, 0x5b, 0x1c, - 0x70, 0xc5, 0x75, 0xf6, 0xad, 0xce, 0xdc, 0x14, 0xff, 0x1b, 0x37, 0x86, 0x34, 0xe8, 0xd5, 0xbb, - 0x6d, 0xc1, 0xd7, 0x9a, 0x92, 0xe2, 0xc4, 0x2b, 0x46, 0x08, 0xc4, 0x84, 0x69, 0x35, 0x18, 0xaf, - 0xd8, 0xba, 0xd5, 0xf5, 0xe7, 0xa6, 0x79, 0xe3, 0xfd, 0xb1, 0x21, 0x98, 0x18, 0x67, 0x6e, 0x5d, - 0x91, 0x9f, 0x32, 0x9d, 0x48, 0xf6, 0x31, 0x85, 0x39, 0xff, 0x06, 0x3c, 0x3f, 0x30, 0x36, 0x90, - 0x59, 0x28, 0x1d, 0xd2, 0x63, 0x3e, 0xf4, 0xd5, 0x91, 0x3d, 0x92, 0xcb, 0x50, 0x39, 0xd2, 0xed, - 0x3e, 0x9d, 0x2b, 0xf2, 0x34, 0xf1, 0xf2, 0x33, 0xc5, 0xd7, 0x0b, 0xda, 0x5f, 0x2f, 0xc1, 0xa4, - 0x1a, 0x71, 0xda, 0x96, 0x73, 0x48, 0xde, 0x86, 0x92, 0xed, 0x76, 0xe4, 0xb8, 0xf9, 0x73, 0x23, - 0x8f, 0x62, 0x9b, 0x6e, 0xa7, 0x55, 0x3d, 0x3d, 0x69, 0x96, 0x36, 0xdd, 0x0e, 0x32, 0x44, 0x62, - 0x40, 0xe5, 0x50, 0xdf, 0x3f, 0xd4, 0x79, 0x19, 0x1a, 0x4b, 0xad, 0x91, 0xa1, 0xef, 0x30, 0x14, - 0x56, 0xd6, 0x56, 0xfd, 0xf4, 0xa4, 0x59, 0xe1, 0xaf, 0x28, 0xb0, 0x89, 0x0b, 0xf5, 0x3d, 0x5b, - 0x37, 0x0e, 0x0f, 0x5c, 0x9b, 0xce, 0x95, 0x72, 0x0a, 0x6a, 0x29, 0x24, 0xf1, 0x9b, 0xc3, 0x57, - 0x8c, 0x64, 0x10, 0x03, 0x26, 0xfa, 0xa6, 0x6f, 0x39, 0x87, 0x72, 0x0c, 0x7c, 0x63, 0x64, 0x69, - 0xbb, 0xab, 0xfc, 0x9b, 0xe0, 0xf4, 0xa4, 0x39, 0x21, 0x9e, 0x51, 0x42, 0x6b, 0xff, 0x67, 0x12, - 0xa6, 0xd5, 0x4f, 0xba, 0x4f, 0xbd, 0x80, 0x3e, 0x24, 0x37, 0xa0, 0xec, 0xb0, 0xae, 0xc9, 0x7f, - 0x72, 0x6b, 0x52, 0x36, 0x97, 0x32, 0xef, 0x92, 0x9c, 0xc2, 0x4a, 0x26, 0x9a, 0x8a, 0xac, 0xf0, - 0xd1, 0x4b, 0xd6, 0xe6, 0x30, 0xa2, 0x64, 0xe2, 0x19, 0x25, 0x34, 0x79, 0x17, 0xca, 0xfc, 0xe3, - 0x45, 0x55, 0x7f, 0x65, 0x74, 0x11, 0xec, 0xd3, 0x6b, 0xec, 0x0b, 0xf8, 0x87, 0x73, 0x50, 0xd6, - 0x14, 0xfb, 0xe6, 0xbe, 0xac, 0xd8, 0x9f, 0xcb, 0x51, 0xb1, 0x6b, 0xa2, 0x29, 0xee, 0xae, 0xae, - 0x21, 0x43, 0x24, 0x7f, 0xb1, 0x00, 0xcf, 0x1b, 0xae, 0x13, 0xe8, 0x4c, 0xcf, 0x50, 0x93, 0xec, - 0x5c, 0x85, 0xcb, 0x79, 0x6b, 0x64, 0x39, 0x2b, 0x69, 0xc4, 0xd6, 0x0b, 0x6c, 0xce, 0x18, 0x48, - 0xc6, 0x41, 0xd9, 0xe4, 0x2f, 0x17, 0xe0, 0x05, 0x36, 0x96, 0x0f, 0x30, 0xf3, 0x19, 0x68, 0xbc, - 0xa5, 0xba, 0x7a, 0x7a, 0xd2, 0x7c, 0x61, 0x23, 0x4b, 0x18, 0x66, 0x97, 0x81, 0x95, 0xee, 0x92, - 0x3e, 0xa8, 0x96, 0xf0, 0xd9, 0xad, 0xb1, 0xb4, 0x39, 0x4e, 0x55, 0xa7, 0xf5, 0x19, 0xd9, 0x94, - 0xb3, 0x34, 0x3b, 0xcc, 0x2a, 0x05, 0xb9, 0x05, 0xd5, 0x23, 0xd7, 0xee, 0x77, 0xa9, 0x3f, 0x57, - 0xe3, 0x43, 0xec, 0x7c, 0xd6, 0x10, 0x7b, 0x9f, 0xb3, 0xb4, 0x66, 0x24, 0x7c, 0x55, 0xbc, 0xfb, - 0xa8, 0xf2, 0x12, 0x0b, 0x26, 0x6c, 0xab, 0x6b, 0x05, 0x3e, 0x9f, 0x38, 0x1b, 0x4b, 0xb7, 0x46, - 0xfe, 0x2c, 0xd1, 0x45, 0x37, 0x39, 0x98, 0xe8, 0x35, 0xe2, 0x19, 0xa5, 0x00, 0x36, 0x14, 0xfa, - 0x86, 0x6e, 0x8b, 0x89, 0xb5, 0xb1, 0xf4, 0xd5, 0xd1, 0xbb, 0x0d, 0x43, 0x69, 0x4d, 0xc9, 0x6f, - 0xaa, 0xf0, 0x57, 0x14, 0xd8, 0xe4, 0x17, 0x60, 0x3a, 0xf1, 0x37, 0xfd, 0xb9, 0x06, 0xaf, 0x9d, - 0x97, 0xb2, 0x6a, 0x27, 0xe4, 0x8a, 0x66, 0x9e, 0x44, 0x0b, 0xf1, 0x31, 0x05, 0x46, 0xee, 0x40, - 0xcd, 0xb7, 0x4c, 0x6a, 0xe8, 0x9e, 0x3f, 0x37, 0x79, 0x16, 0xe0, 0x59, 0x09, 0x5c, 0x6b, 0xcb, - 0x6c, 0x18, 0x02, 0x90, 0x05, 0x80, 0x9e, 0xee, 0x05, 0x96, 0x50, 0x54, 0xa7, 0xb8, 0xd2, 0x34, - 0x7d, 0x7a, 0xd2, 0x84, 0xed, 0x30, 0x15, 0x63, 0x1c, 0x8c, 0x9f, 0xe5, 0xdd, 0x70, 0x7a, 0xfd, - 0x40, 0x4c, 0xac, 0x75, 0xc1, 0xdf, 0x0e, 0x53, 0x31, 0xc6, 0x41, 0x7e, 0xab, 0x00, 0x9f, 0x89, - 0x5e, 0x07, 0x3b, 0xd9, 0xcc, 0xd8, 0x3b, 0x59, 0xf3, 0xf4, 0xa4, 0xf9, 0x99, 0xf6, 0x70, 0x91, - 0xf8, 0xb8, 0xf2, 0x90, 0x0f, 0x0b, 0x30, 0xdd, 0xef, 0x99, 0x7a, 0x40, 0xdb, 0x01, 0x5b, 0xf1, - 0x74, 0x8e, 0xe7, 0x66, 0x79, 0x11, 0xd7, 0x47, 0x1f, 0x05, 0x13, 0x70, 0xd1, 0x6f, 0x4e, 0xa6, - 0x63, 0x4a, 0xac, 0xf6, 0x36, 0x4c, 0x2d, 0xf7, 0x83, 0x03, 0xd7, 0xb3, 0x3e, 0xe0, 0xea, 0x3f, - 0x59, 0x83, 0x4a, 0xc0, 0xd5, 0x38, 0xa1, 0x21, 0x7c, 0x3e, 0xeb, 0xa7, 0x0b, 0x95, 0xfa, 0x0e, - 0x3d, 0x56, 0x7a, 0x89, 0x98, 0xa9, 0x85, 0x5a, 0x27, 0xb2, 0x6b, 0x7f, 0xba, 0x00, 0xd5, 0x96, - 0x6e, 0x1c, 0xba, 0xfb, 0xfb, 0xe4, 0x1d, 0xa8, 0x59, 0x4e, 0x40, 0xbd, 0x23, 0xdd, 0x96, 0xb0, - 0x0b, 0x31, 0xd8, 0x70, 0x41, 0x18, 0x7d, 0x1e, 0x5b, 0x7d, 0x31, 0x41, 0xab, 0x7d, 0xb9, 0x6a, - 0xe1, 0x9a, 0xf1, 0x86, 0xc4, 0xc0, 0x10, 0x8d, 0x34, 0xa1, 0xe2, 0x07, 0xb4, 0xe7, 0xf3, 0x39, - 0x70, 0x4a, 0x14, 0xa3, 0xcd, 0x12, 0x50, 0xa4, 0x6b, 0x7f, 0xad, 0x00, 0xf5, 0x96, 0xee, 0x5b, - 0x06, 0xfb, 0x4a, 0xb2, 0x02, 0xe5, 0xbe, 0x4f, 0xbd, 0xf3, 0x7d, 0x1b, 0x9f, 0xb6, 0x76, 0x7d, - 0xea, 0x21, 0xcf, 0x4c, 0xee, 0x41, 0xad, 0xa7, 0xfb, 0xfe, 0x03, 0xd7, 0x33, 0xe5, 0xd4, 0x7b, - 0x46, 0x20, 0xb1, 0x4c, 0x90, 0x59, 0x31, 0x04, 0xd1, 0x1a, 0x10, 0xe9, 0x1e, 0xda, 0xef, 0x15, - 0xe0, 0x52, 0xab, 0xbf, 0xbf, 0x4f, 0x3d, 0xa9, 0x15, 0x4b, 0x7d, 0x93, 0x42, 0xc5, 0xa3, 0xa6, - 0xe5, 0xcb, 0xb2, 0xaf, 0x8e, 0xdc, 0x50, 0x90, 0xa1, 0x48, 0xf5, 0x96, 0xd7, 0x17, 0x4f, 0x40, - 0x81, 0x4e, 0xfa, 0x50, 0x7f, 0x9f, 0xb2, 0xd5, 0x38, 0xd5, 0xbb, 0xf2, 0xeb, 0x6e, 0x8f, 0x2c, - 0xea, 0x2d, 0x1a, 0xb4, 0x39, 0x52, 0x5c, 0x9b, 0x0e, 0x13, 0x31, 0x92, 0xa4, 0xfd, 0x4e, 0x05, - 0x26, 0x57, 0xdc, 0xee, 0x9e, 0xe5, 0x50, 0xf3, 0x96, 0xd9, 0xa1, 0xe4, 0x3d, 0x28, 0x53, 0xb3, - 0x43, 0xe5, 0xd7, 0x8e, 0xae, 0x78, 0x30, 0xb0, 0x48, 0x7d, 0x62, 0x6f, 0xc8, 0x81, 0xc9, 0x26, - 0x4c, 0xef, 0x7b, 0x6e, 0x57, 0x8c, 0xe5, 0x3b, 0xc7, 0x3d, 0xa9, 0x3b, 0xb7, 0x7e, 0x4c, 0x75, - 0x9c, 0xb5, 0x04, 0xf5, 0xd1, 0x49, 0x13, 0xa2, 0x37, 0x4c, 0xe5, 0x25, 0xef, 0xc0, 0x5c, 0x94, - 0x12, 0x0e, 0x6a, 0x2b, 0x6c, 0x39, 0xc3, 0x75, 0xa7, 0x4a, 0xeb, 0xda, 0xe9, 0x49, 0x73, 0x6e, - 0x6d, 0x08, 0x0f, 0x0e, 0xcd, 0xcd, 0x86, 0x8a, 0xd9, 0x88, 0x28, 0x26, 0x1a, 0xa9, 0x32, 0x8d, - 0x69, 0x06, 0xe3, 0xeb, 0xbe, 0xb5, 0x94, 0x08, 0x1c, 0x10, 0x4a, 0xd6, 0x60, 0x32, 0x70, 0x63, - 0xf5, 0x55, 0xe1, 0xf5, 0xa5, 0x29, 0x43, 0xc5, 0x8e, 0x3b, 0xb4, 0xb6, 0x12, 0xf9, 0x08, 0xc2, - 0x15, 0xf5, 0x9e, 0xaa, 0xa9, 0x09, 0x5e, 0x53, 0xf3, 0xa7, 0x27, 0xcd, 0x2b, 0x3b, 0x99, 0x1c, - 0x38, 0x24, 0x27, 0xf9, 0x95, 0x02, 0x4c, 0x2b, 0x92, 0xac, 0xa3, 0xea, 0x38, 0xeb, 0x88, 0xb0, - 0x16, 0xb1, 0x93, 0x10, 0x80, 0x29, 0x81, 0xda, 0xf7, 0xaa, 0x50, 0x0f, 0x87, 0x7a, 0xf2, 0x39, - 0xa8, 0x70, 0x13, 0x84, 0xd4, 0xe0, 0xc3, 0x39, 0x9c, 0x5b, 0x2a, 0x50, 0xd0, 0xc8, 0xe7, 0xa1, - 0x6a, 0xb8, 0xdd, 0xae, 0xee, 0x98, 0xdc, 0xac, 0x54, 0x6f, 0x35, 0x98, 0xea, 0xb2, 0x22, 0x92, - 0x50, 0xd1, 0xc8, 0x35, 0x28, 0xeb, 0x5e, 0x47, 0x58, 0x78, 0xea, 0x62, 0x3c, 0x5a, 0xf6, 0x3a, - 0x3e, 0xf2, 0x54, 0xf2, 0x65, 0x28, 0x51, 0xe7, 0x68, 0xae, 0x3c, 0x5c, 0x37, 0xba, 0xe5, 0x1c, - 0xdd, 0xd7, 0xbd, 0x56, 0x43, 0x96, 0xa1, 0x74, 0xcb, 0x39, 0x42, 0x96, 0x87, 0x6c, 0x42, 0x95, - 0x3a, 0x47, 0xec, 0xdf, 0x4b, 0xd3, 0xcb, 0x67, 0x87, 0x64, 0x67, 0x2c, 0x72, 0x99, 0x10, 0x6a, - 0x58, 0x32, 0x19, 0x15, 0x04, 0xf9, 0x3a, 0x4c, 0x0a, 0x65, 0x6b, 0x8b, 0xfd, 0x13, 0x7f, 0x6e, - 0x82, 0x43, 0x36, 0x87, 0x6b, 0x6b, 0x9c, 0x2f, 0x32, 0x75, 0xc5, 0x12, 0x7d, 0x4c, 0x40, 0x91, - 0xaf, 0x43, 0x5d, 0xad, 0x8c, 0xd5, 0x9f, 0xcd, 0xb4, 0x12, 0xa9, 0xe5, 0x34, 0xd2, 0x6f, 0xf6, - 0x2d, 0x8f, 0x76, 0xa9, 0x13, 0xf8, 0xad, 0xe7, 0x95, 0xdd, 0x40, 0x51, 0x7d, 0x8c, 0xd0, 0xc8, - 0xde, 0xa0, 0xb9, 0x4b, 0xd8, 0x6a, 0x3e, 0x37, 0x64, 0x54, 0x1f, 0xc1, 0xd6, 0xf5, 0x0d, 0x98, - 0x09, 0xed, 0x51, 0xd2, 0xa4, 0x21, 0xac, 0x37, 0x5f, 0x64, 0xd9, 0x37, 0x92, 0xa4, 0x47, 0x27, - 0xcd, 0x97, 0x32, 0x8c, 0x1a, 0x11, 0x03, 0xa6, 0xc1, 0xc8, 0x07, 0x30, 0xed, 0x51, 0xdd, 0xb4, - 0x1c, 0xea, 0xfb, 0xdb, 0x9e, 0xbb, 0x97, 0x5f, 0xf3, 0xe4, 0x28, 0xa2, 0xd9, 0x63, 0x02, 0x19, - 0x53, 0x92, 0xc8, 0x03, 0x98, 0xb2, 0xad, 0x23, 0x1a, 0x89, 0x6e, 0x8c, 0x45, 0xf4, 0xf3, 0xa7, - 0x27, 0xcd, 0xa9, 0xcd, 0x38, 0x30, 0x26, 0xe5, 0x30, 0x4d, 0xa5, 0xe7, 0x7a, 0x81, 0x52, 0x4f, - 0x3f, 0xfb, 0x58, 0xf5, 0x74, 0xdb, 0xf5, 0x82, 0xa8, 0x13, 0xb2, 0x37, 0x1f, 0x45, 0x76, 0xed, - 0x6f, 0x55, 0x60, 0x70, 0x11, 0x97, 0x6c, 0x71, 0x85, 0x71, 0xb7, 0xb8, 0x74, 0x6b, 0x10, 0x73, - 0xcf, 0xeb, 0x32, 0xdb, 0x18, 0x5a, 0x44, 0x46, 0xab, 0x2e, 0x8d, 0xbb, 0x55, 0x3f, 0x33, 0x03, - 0xcf, 0x60, 0xf3, 0x9f, 0xf8, 0xf8, 0x9a, 0x7f, 0xf5, 0xe9, 0x34, 0x7f, 0xed, 0xbb, 0x65, 0x98, - 0x5e, 0xd5, 0x69, 0xd7, 0x75, 0x9e, 0xb8, 0x8e, 0x2f, 0x3c, 0x13, 0xeb, 0xf8, 0x9b, 0x50, 0xf3, - 0x68, 0xcf, 0xb6, 0x0c, 0x5d, 0xa8, 0xeb, 0xd2, 0x6e, 0x8e, 0x32, 0x0d, 0x43, 0xea, 0x10, 0xfb, - 0x4d, 0xe9, 0x99, 0xb4, 0xdf, 0x94, 0x3f, 0x7e, 0xfb, 0x8d, 0xf6, 0x2b, 0x45, 0xe0, 0xaa, 0x2d, - 0xb9, 0x01, 0x65, 0xa6, 0xb6, 0xa5, 0xad, 0x86, 0xbc, 0xb7, 0x70, 0x0a, 0x99, 0x87, 0x62, 0xe0, - 0xca, 0xe1, 0x06, 0x24, 0xbd, 0xb8, 0xe3, 0x62, 0x31, 0x70, 0xc9, 0x07, 0x00, 0x86, 0xeb, 0x98, - 0x96, 0x72, 0x27, 0xe5, 0xfb, 0xb0, 0x35, 0xd7, 0x7b, 0xa0, 0x7b, 0xe6, 0x4a, 0x88, 0x28, 0x56, - 0xf0, 0xd1, 0x3b, 0xc6, 0xa4, 0x91, 0x37, 0x60, 0xc2, 0x75, 0xd6, 0xfa, 0xb6, 0xcd, 0x2b, 0xb4, - 0xde, 0xfa, 0xc2, 0xe9, 0x49, 0x73, 0xe2, 0x1e, 0x4f, 0x79, 0x74, 0xd2, 0xbc, 0x2a, 0x56, 0x44, - 0xec, 0xed, 0x6d, 0xcf, 0x0a, 0x2c, 0xa7, 0x13, 0x2e, 0x68, 0x65, 0x36, 0xed, 0x57, 0x0b, 0xd0, - 0x58, 0xb3, 0x1e, 0x52, 0xf3, 0x6d, 0xcb, 0x31, 0xdd, 0x07, 0x04, 0x61, 0xc2, 0xa6, 0x4e, 0x27, - 0x38, 0x18, 0x71, 0xc5, 0x29, 0xec, 0x3a, 0x1c, 0x01, 0x25, 0x12, 0x59, 0x84, 0xba, 0x58, 0xaf, - 0x58, 0x4e, 0x87, 0xd7, 0x61, 0x2d, 0x1a, 0xe9, 0xdb, 0x8a, 0x80, 0x11, 0x8f, 0x76, 0x0c, 0xcf, - 0x0f, 0x54, 0x03, 0x31, 0xa1, 0x1c, 0xe8, 0x1d, 0x35, 0xa9, 0xac, 0x8d, 0x5c, 0xc1, 0x3b, 0x7a, - 0x27, 0x56, 0xb9, 0x5c, 0x2b, 0xdc, 0xd1, 0x99, 0x56, 0xc8, 0xd0, 0xb5, 0x3f, 0x28, 0x40, 0x6d, - 0xad, 0xef, 0x18, 0x7c, 0x51, 0xff, 0x64, 0x6b, 0xb2, 0x52, 0x31, 0x8b, 0x99, 0x2a, 0x66, 0x1f, - 0x26, 0x0e, 0x1f, 0x84, 0x2a, 0x68, 0x63, 0x69, 0x6b, 0xf4, 0x56, 0x21, 0x8b, 0xb4, 0x70, 0x87, - 0xe3, 0x09, 0x67, 0xe7, 0xb4, 0x2c, 0xd0, 0xc4, 0x9d, 0xb7, 0xb9, 0x50, 0x29, 0x6c, 0xfe, 0xcb, - 0xd0, 0x88, 0xb1, 0x9d, 0xcb, 0xef, 0xf1, 0xb7, 0xcb, 0x30, 0xb1, 0xde, 0x6e, 0x2f, 0x6f, 0x6f, - 0x90, 0x57, 0xa1, 0x21, 0xfd, 0x60, 0x77, 0xa3, 0x3a, 0x08, 0xdd, 0xa0, 0xed, 0x88, 0x84, 0x71, - 0x3e, 0xa6, 0xc0, 0x7b, 0x54, 0xb7, 0xbb, 0xb2, 0xb3, 0x84, 0xba, 0x03, 0xb2, 0x44, 0x14, 0x34, - 0xa2, 0xc3, 0x74, 0xdf, 0xa7, 0x1e, 0xab, 0x42, 0xb1, 0xde, 0x97, 0xdd, 0xe6, 0x8c, 0x16, 0x01, - 0x3e, 0xc1, 0xec, 0x26, 0x00, 0x30, 0x05, 0x48, 0x5e, 0x87, 0x9a, 0xde, 0x0f, 0x0e, 0xf8, 0x92, - 0x4b, 0xf4, 0x8d, 0x6b, 0xdc, 0x4d, 0x28, 0xd3, 0x1e, 0x9d, 0x34, 0x27, 0xef, 0x60, 0xeb, 0x55, - 0xf5, 0x8e, 0x21, 0x37, 0x2b, 0x9c, 0xb2, 0x31, 0xc8, 0xc2, 0x55, 0xce, 0x5d, 0xb8, 0xed, 0x04, - 0x00, 0xa6, 0x00, 0xc9, 0xbb, 0x30, 0x79, 0x48, 0x8f, 0x03, 0x7d, 0x4f, 0x0a, 0x98, 0x38, 0x8f, - 0x80, 0x59, 0xa6, 0xf4, 0xdf, 0x89, 0x65, 0xc7, 0x04, 0x18, 0xf1, 0xe1, 0xf2, 0x21, 0xf5, 0xf6, - 0xa8, 0xe7, 0x4a, 0x7b, 0x85, 0x14, 0x52, 0x3d, 0x8f, 0x90, 0xb9, 0xd3, 0x93, 0xe6, 0xe5, 0x3b, - 0x19, 0x30, 0x98, 0x09, 0xae, 0xfd, 0xdf, 0x22, 0xcc, 0xac, 0x8b, 0x40, 0x04, 0xd7, 0x13, 0x9a, - 0x07, 0xb9, 0x0a, 0x25, 0xaf, 0xd7, 0xe7, 0x2d, 0xa7, 0x24, 0x5c, 0x0d, 0xb8, 0xbd, 0x8b, 0x2c, - 0x8d, 0xbc, 0x03, 0x35, 0x53, 0x0e, 0x19, 0xd2, 0x5c, 0x32, 0x92, 0x69, 0x4b, 0xbd, 0x61, 0x88, - 0xc6, 0xd6, 0x86, 0x5d, 0xbf, 0xd3, 0xb6, 0x3e, 0xa0, 0xd2, 0x82, 0xc0, 0xd7, 0x86, 0x5b, 0x22, - 0x09, 0x15, 0x8d, 0xcd, 0xaa, 0x87, 0xf4, 0x58, 0xac, 0x9f, 0xcb, 0xd1, 0xac, 0x7a, 0x47, 0xa6, - 0x61, 0x48, 0x25, 0x4d, 0xd5, 0x59, 0x58, 0x2b, 0x28, 0x0b, 0xdb, 0xcf, 0x7d, 0x96, 0x20, 0xfb, - 0x0d, 0x1b, 0x32, 0xdf, 0xb7, 0x82, 0x80, 0x7a, 0xf2, 0x37, 0x8e, 0x34, 0x64, 0xbe, 0xc5, 0x11, - 0x50, 0x22, 0x91, 0x9f, 0x80, 0x3a, 0x07, 0x6f, 0xd9, 0xee, 0x1e, 0xff, 0x71, 0x75, 0x61, 0x05, - 0xba, 0xaf, 0x12, 0x31, 0xa2, 0x6b, 0x7f, 0x58, 0x84, 0x2b, 0xeb, 0x34, 0x10, 0x5a, 0xcd, 0x2a, - 0xed, 0xd9, 0xee, 0x31, 0xd3, 0xa7, 0x91, 0x7e, 0x93, 0xbc, 0x09, 0x60, 0xf9, 0x7b, 0xed, 0x23, - 0x83, 0xf7, 0x03, 0xd1, 0x87, 0x6f, 0xc8, 0x2e, 0x09, 0x1b, 0xed, 0x96, 0xa4, 0x3c, 0x4a, 0xbc, - 0x61, 0x2c, 0x4f, 0xb4, 0x20, 0x2f, 0x3e, 0x66, 0x41, 0xde, 0x06, 0xe8, 0x45, 0x5a, 0x79, 0x89, - 0x73, 0xfe, 0xb4, 0x12, 0x73, 0x1e, 0x85, 0x3c, 0x06, 0x93, 0x47, 0x4f, 0x76, 0x60, 0xd6, 0xa4, - 0xfb, 0x7a, 0xdf, 0x0e, 0xc2, 0x95, 0x84, 0xec, 0xc4, 0x67, 0x5f, 0x8c, 0x84, 0x41, 0x12, 0xab, - 0x29, 0x24, 0x1c, 0xc0, 0xd6, 0xfe, 0x4e, 0x09, 0xe6, 0xd7, 0x69, 0x10, 0xda, 0xe8, 0xe4, 0xe8, - 0xd8, 0xee, 0x51, 0x83, 0xfd, 0x85, 0x0f, 0x0b, 0x30, 0x61, 0xeb, 0x7b, 0xd4, 0x66, 0xb3, 0x17, - 0xfb, 0x9a, 0xf7, 0x46, 0x9e, 0x08, 0x86, 0x4b, 0x59, 0xd8, 0xe4, 0x12, 0x52, 0x53, 0x83, 0x48, - 0x44, 0x29, 0x9e, 0x0d, 0xea, 0x86, 0xdd, 0xf7, 0x03, 0xb1, 0xb2, 0x93, 0xfa, 0x64, 0x38, 0xa8, - 0xaf, 0x44, 0x24, 0x8c, 0xf3, 0x91, 0x25, 0x00, 0xc3, 0xb6, 0xa8, 0x13, 0xf0, 0x5c, 0xa2, 0x5f, - 0x11, 0xf5, 0x7f, 0x57, 0x42, 0x0a, 0xc6, 0xb8, 0x98, 0xa8, 0xae, 0xeb, 0x58, 0x81, 0x2b, 0x44, - 0x95, 0x93, 0xa2, 0xb6, 0x22, 0x12, 0xc6, 0xf9, 0x78, 0x36, 0x1a, 0x78, 0x96, 0xe1, 0xf3, 0x6c, - 0x95, 0x54, 0xb6, 0x88, 0x84, 0x71, 0x3e, 0x36, 0xe7, 0xc5, 0xbe, 0xff, 0x5c, 0x73, 0xde, 0x6f, - 0xd6, 0xe1, 0x7a, 0xa2, 0x5a, 0x03, 0x3d, 0xa0, 0xfb, 0x7d, 0xbb, 0x4d, 0x03, 0xf5, 0x03, 0x47, - 0x9c, 0x0b, 0xff, 0x5c, 0xf4, 0xdf, 0x45, 0xf8, 0x93, 0x31, 0x9e, 0xff, 0x3e, 0x50, 0xc0, 0x33, - 0xfd, 0xfb, 0x45, 0xa8, 0x3b, 0x7a, 0xe0, 0xf3, 0x8e, 0x2b, 0xfb, 0x68, 0xa8, 0x86, 0xdd, 0x55, - 0x04, 0x8c, 0x78, 0xc8, 0x36, 0x5c, 0x96, 0x55, 0x7c, 0xeb, 0x21, 0x5b, 0xf3, 0x53, 0x4f, 0xe4, - 0x95, 0xd3, 0xa9, 0xcc, 0x7b, 0x79, 0x2b, 0x83, 0x07, 0x33, 0x73, 0x92, 0x2d, 0xb8, 0x64, 0x88, - 0x90, 0x10, 0x6a, 0xbb, 0xba, 0xa9, 0x00, 0x85, 0x49, 0x34, 0x5c, 0x1a, 0xad, 0x0c, 0xb2, 0x60, - 0x56, 0xbe, 0x74, 0x6b, 0x9e, 0x18, 0xa9, 0x35, 0x57, 0x47, 0x69, 0xcd, 0xb5, 0xd1, 0x5a, 0x73, - 0xfd, 0x6c, 0xad, 0x99, 0xd5, 0x3c, 0x6b, 0x47, 0xd4, 0x63, 0xea, 0x89, 0x98, 0x61, 0x63, 0x11, - 0x47, 0x61, 0xcd, 0xb7, 0x33, 0x78, 0x30, 0x33, 0x27, 0xd9, 0x83, 0x79, 0x91, 0x7e, 0xcb, 0x31, - 0xbc, 0xe3, 0x1e, 0x9b, 0x78, 0x62, 0xb8, 0x8d, 0x84, 0x4d, 0x7a, 0xbe, 0x3d, 0x94, 0x13, 0x1f, - 0x83, 0x42, 0x7e, 0x16, 0xa6, 0xc4, 0x5f, 0xda, 0xd2, 0x7b, 0x1c, 0x56, 0xc4, 0x1f, 0xbd, 0x20, - 0x61, 0xa7, 0x56, 0xe2, 0x44, 0x4c, 0xf2, 0x92, 0x65, 0x98, 0xe9, 0x1d, 0x19, 0xec, 0x71, 0x63, - 0xff, 0x2e, 0xa5, 0x26, 0x35, 0xb9, 0xc3, 0xb3, 0xde, 0x7a, 0x51, 0x59, 0x77, 0xb6, 0x93, 0x64, - 0x4c, 0xf3, 0x93, 0xd7, 0x61, 0xd2, 0x0f, 0x74, 0x2f, 0x90, 0x86, 0xe0, 0xb9, 0x69, 0x11, 0x9f, - 0xa5, 0xec, 0xa4, 0xed, 0x18, 0x0d, 0x13, 0x9c, 0x99, 0xf3, 0xc5, 0xcc, 0xc5, 0xcd, 0x17, 0x79, - 0x46, 0xab, 0x7f, 0x52, 0x84, 0x1b, 0xeb, 0x34, 0xd8, 0x72, 0x1d, 0x69, 0x46, 0xcf, 0x9a, 0xf6, - 0xcf, 0x64, 0x45, 0x4f, 0x4e, 0xda, 0xc5, 0xb1, 0x4e, 0xda, 0xa5, 0x31, 0x4d, 0xda, 0xe5, 0x0b, - 0x9c, 0xb4, 0xff, 0x5e, 0x11, 0x5e, 0x4c, 0xd4, 0xe4, 0xb6, 0x6b, 0xaa, 0x01, 0xff, 0xd3, 0x0a, - 0x3c, 0x43, 0x05, 0x3e, 0x12, 0x7a, 0x27, 0x77, 0x84, 0xa6, 0x34, 0x9e, 0xef, 0xa4, 0x35, 0x9e, - 0x77, 0xf3, 0xcc, 0x7c, 0x19, 0x12, 0xce, 0x34, 0xe3, 0xbd, 0x05, 0xc4, 0x93, 0x6e, 0xdb, 0xc8, - 0x9c, 0x2d, 0x95, 0x9e, 0x30, 0x00, 0x14, 0x07, 0x38, 0x30, 0x23, 0x17, 0x69, 0xc3, 0x0b, 0x3e, - 0x75, 0x02, 0xcb, 0xa1, 0x76, 0x12, 0x4e, 0x68, 0x43, 0x2f, 0x49, 0xb8, 0x17, 0xda, 0x59, 0x4c, - 0x98, 0x9d, 0x37, 0xcf, 0x38, 0xf0, 0x2f, 0x80, 0xab, 0x9c, 0xa2, 0x6a, 0xc6, 0xa6, 0xb1, 0x7c, - 0x98, 0xd6, 0x58, 0xde, 0xcb, 0xff, 0xdf, 0x46, 0xd3, 0x56, 0x96, 0x00, 0xf8, 0x5f, 0x88, 0xab, - 0x2b, 0xe1, 0x24, 0x8d, 0x21, 0x05, 0x63, 0x5c, 0x6c, 0x02, 0x52, 0xf5, 0x1c, 0xd7, 0x54, 0xc2, - 0x09, 0xa8, 0x1d, 0x27, 0x62, 0x92, 0x77, 0xa8, 0xb6, 0x53, 0x19, 0x59, 0xdb, 0x79, 0x0b, 0x48, - 0xc2, 0xf0, 0x28, 0xf0, 0x26, 0x92, 0xf1, 0xc7, 0x1b, 0x03, 0x1c, 0x98, 0x91, 0x6b, 0x48, 0x53, - 0xae, 0x8e, 0xb7, 0x29, 0xd7, 0x46, 0x6f, 0xca, 0xe4, 0x3d, 0xb8, 0xca, 0x45, 0xc9, 0xfa, 0x49, - 0x02, 0x0b, 0xbd, 0xe7, 0xb3, 0x12, 0xf8, 0x2a, 0x0e, 0x63, 0xc4, 0xe1, 0x18, 0xec, 0xff, 0x18, - 0x1e, 0x35, 0x99, 0x70, 0xdd, 0x1e, 0xae, 0x13, 0xad, 0x64, 0xf0, 0x60, 0x66, 0x4e, 0xd6, 0xc4, - 0x02, 0xd6, 0x0c, 0xf5, 0x3d, 0x9b, 0x9a, 0x32, 0xfe, 0x3a, 0x6c, 0x62, 0x3b, 0x9b, 0x6d, 0x49, - 0xc1, 0x18, 0x57, 0x96, 0x9a, 0x32, 0x79, 0x4e, 0x35, 0x65, 0x9d, 0x5b, 0xe9, 0xf7, 0x13, 0xda, - 0x90, 0xd4, 0x75, 0xc2, 0x88, 0xfa, 0x95, 0x34, 0x03, 0x0e, 0xe6, 0xe1, 0x5a, 0xa2, 0xe1, 0x59, - 0xbd, 0xc0, 0x4f, 0x62, 0x4d, 0xa7, 0xb4, 0xc4, 0x0c, 0x1e, 0xcc, 0xcc, 0xc9, 0xf4, 0xf3, 0x03, - 0xaa, 0xdb, 0xc1, 0x41, 0x12, 0x70, 0x26, 0xa9, 0x9f, 0xdf, 0x1e, 0x64, 0xc1, 0xac, 0x7c, 0x99, - 0x13, 0xd2, 0xec, 0xb3, 0xa9, 0x56, 0x7d, 0xbb, 0x04, 0x57, 0xd7, 0x69, 0x10, 0x86, 0xa6, 0x7d, - 0x6a, 0x46, 0xf9, 0x18, 0xcc, 0x28, 0xbf, 0x51, 0x81, 0x4b, 0xeb, 0x34, 0x18, 0xd0, 0xc6, 0xfe, - 0x88, 0x56, 0xff, 0x16, 0x5c, 0x8a, 0xa2, 0x21, 0xdb, 0x81, 0xeb, 0x89, 0xb9, 0x3c, 0xb5, 0x5a, - 0x6e, 0x0f, 0xb2, 0x60, 0x56, 0x3e, 0xf2, 0x75, 0x78, 0x91, 0x4f, 0xf5, 0x4e, 0x47, 0xd8, 0x67, - 0x85, 0x31, 0x21, 0xb6, 0x9f, 0xa7, 0x29, 0x21, 0x5f, 0x6c, 0x67, 0xb3, 0xe1, 0xb0, 0xfc, 0xe4, - 0x5b, 0x30, 0xd9, 0xb3, 0x7a, 0xd4, 0xb6, 0x1c, 0xae, 0x9f, 0xe5, 0x0e, 0x22, 0xda, 0x8e, 0x81, - 0x45, 0x0b, 0xb8, 0x78, 0x2a, 0x26, 0x04, 0x66, 0xb6, 0xd4, 0xda, 0x05, 0xb6, 0xd4, 0xff, 0x59, - 0x84, 0xea, 0xba, 0xe7, 0xf6, 0x7b, 0xad, 0x63, 0xd2, 0x81, 0x89, 0x07, 0xdc, 0x79, 0x26, 0x5d, - 0x53, 0xa3, 0xef, 0x28, 0x10, 0x3e, 0xb8, 0x48, 0x25, 0x12, 0xef, 0x28, 0xe1, 0x59, 0x23, 0x3e, - 0xa4, 0xc7, 0xd4, 0x94, 0x3e, 0xb4, 0xb0, 0x11, 0xdf, 0x61, 0x89, 0x28, 0x68, 0xa4, 0x0b, 0x33, - 0xba, 0x6d, 0xbb, 0x0f, 0xa8, 0xb9, 0xa9, 0x07, 0xdc, 0xef, 0x2d, 0x7d, 0x2b, 0xe7, 0x35, 0x4b, - 0xf3, 0x60, 0x86, 0xe5, 0x24, 0x14, 0xa6, 0xb1, 0xc9, 0xfb, 0x50, 0xf5, 0x03, 0xd7, 0x53, 0xca, - 0x56, 0x63, 0x69, 0x65, 0xf4, 0x9f, 0xde, 0xfa, 0x5a, 0x5b, 0x40, 0x09, 0x9b, 0xbd, 0x7c, 0x41, - 0x25, 0x40, 0xfb, 0xf5, 0x02, 0xc0, 0xed, 0x9d, 0x9d, 0x6d, 0xe9, 0x5e, 0x30, 0xa1, 0xac, 0xf7, - 0x43, 0x47, 0xe5, 0xe8, 0x0e, 0xc1, 0x44, 0x20, 0xaf, 0xf4, 0xe1, 0xf5, 0x83, 0x03, 0xe4, 0xe8, - 0xe4, 0xc7, 0xa1, 0x2a, 0x15, 0x64, 0x59, 0xed, 0x61, 0x3c, 0x85, 0x54, 0xa2, 0x51, 0xd1, 0xb5, - 0xdf, 0x2e, 0x02, 0x6c, 0x98, 0x36, 0x6d, 0xab, 0x4d, 0x20, 0xf5, 0xe0, 0xc0, 0xa3, 0xfe, 0x81, - 0x6b, 0x9b, 0x23, 0x7a, 0x53, 0xb9, 0xcd, 0x7f, 0x47, 0x81, 0x60, 0x84, 0x47, 0x4c, 0x98, 0xf4, - 0x03, 0xda, 0x53, 0xb1, 0xbd, 0x23, 0x3a, 0x51, 0x66, 0x85, 0x5d, 0x24, 0xc2, 0xc1, 0x04, 0x2a, - 0xd1, 0xa1, 0x61, 0x39, 0x86, 0xe8, 0x20, 0xad, 0xe3, 0x11, 0x1b, 0xd2, 0x0c, 0x5b, 0x71, 0x6c, - 0x44, 0x30, 0x18, 0xc7, 0xd4, 0x7e, 0xb7, 0x08, 0x57, 0xb8, 0x3c, 0x56, 0x8c, 0x44, 0x04, 0x2f, - 0xf9, 0x93, 0x03, 0x1b, 0x56, 0xff, 0xf8, 0xd9, 0x44, 0x8b, 0xfd, 0x8e, 0x5b, 0x34, 0xd0, 0x23, - 0x7d, 0x2e, 0x4a, 0x8b, 0xed, 0x52, 0xed, 0x43, 0xd9, 0x67, 0xe3, 0x95, 0xa8, 0xbd, 0xf6, 0xc8, - 0x4d, 0x28, 0xfb, 0x03, 0xf8, 0xe8, 0x15, 0x7a, 0x8d, 0xf9, 0xa8, 0xc5, 0xc5, 0x91, 0x5f, 0x82, - 0x09, 0x3f, 0xd0, 0x83, 0xbe, 0xea, 0x9a, 0xbb, 0xe3, 0x16, 0xcc, 0xc1, 0xa3, 0x71, 0x44, 0xbc, - 0xa3, 0x14, 0xaa, 0xfd, 0x6e, 0x01, 0xe6, 0xb3, 0x33, 0x6e, 0x5a, 0x7e, 0x40, 0xfe, 0xc4, 0x40, - 0xb5, 0x9f, 0xf1, 0x8f, 0xb3, 0xdc, 0xbc, 0xd2, 0xc3, 0x3d, 0x0d, 0x2a, 0x25, 0x56, 0xe5, 0x01, - 0x54, 0xac, 0x80, 0x76, 0xd5, 0xfa, 0xf2, 0xde, 0x98, 0x3f, 0x3d, 0x36, 0xb5, 0x33, 0x29, 0x28, - 0x84, 0x69, 0xdf, 0x2d, 0x0e, 0xfb, 0x64, 0x3e, 0x7d, 0xd8, 0xc9, 0x28, 0xf1, 0x3b, 0xf9, 0xa2, - 0xc4, 0x93, 0x05, 0x1a, 0x0c, 0x16, 0xff, 0x53, 0x83, 0xc1, 0xe2, 0xf7, 0xf2, 0x07, 0x8b, 0xa7, - 0xaa, 0x61, 0x68, 0xcc, 0xf8, 0x47, 0x25, 0xb8, 0xf6, 0xb8, 0x66, 0xc3, 0xe6, 0x33, 0xd9, 0x3a, - 0xf3, 0xce, 0x67, 0x8f, 0x6f, 0x87, 0x64, 0x09, 0x2a, 0xbd, 0x03, 0xdd, 0x57, 0x4a, 0xd9, 0xb5, - 0x30, 0xcc, 0x90, 0x25, 0x3e, 0x62, 0x83, 0x06, 0x57, 0xe6, 0xf8, 0x2b, 0x0a, 0x56, 0x36, 0x1c, - 0x77, 0xa9, 0xef, 0x47, 0x36, 0x81, 0x70, 0x38, 0xde, 0x12, 0xc9, 0xa8, 0xe8, 0x24, 0x80, 0x09, - 0x61, 0x62, 0x96, 0x33, 0xd3, 0xe8, 0x81, 0x5c, 0x19, 0x1b, 0x0b, 0xa2, 0x8f, 0x92, 0xde, 0x0a, - 0x29, 0x8b, 0x2c, 0x40, 0x39, 0x88, 0xc2, 0xbc, 0xd5, 0xd2, 0xbc, 0x9c, 0xa1, 0x9f, 0x72, 0x3e, - 0xb6, 0xb0, 0x77, 0xf7, 0xb8, 0x51, 0xdd, 0x94, 0xfe, 0x73, 0xcb, 0x75, 0xb8, 0x42, 0x56, 0x8a, - 0x16, 0xf6, 0xf7, 0x06, 0x38, 0x30, 0x23, 0x97, 0xf6, 0xaf, 0x6b, 0x70, 0x25, 0xbb, 0x3d, 0xb0, - 0x7a, 0x3b, 0xa2, 0x9e, 0xcf, 0xb0, 0x0b, 0xc9, 0x7a, 0xbb, 0x2f, 0x92, 0x51, 0xd1, 0x3f, 0xd1, - 0x01, 0x67, 0xbf, 0x51, 0x80, 0xab, 0x9e, 0xf4, 0x11, 0x3d, 0x8d, 0xa0, 0xb3, 0x97, 0x84, 0x39, - 0x63, 0x88, 0x40, 0x1c, 0x5e, 0x16, 0xf2, 0x37, 0x0a, 0x30, 0xd7, 0x4d, 0xd9, 0x39, 0x2e, 0x70, - 0xcf, 0x25, 0xdf, 0x47, 0xb1, 0x35, 0x44, 0x1e, 0x0e, 0x2d, 0x09, 0xf9, 0x16, 0x34, 0x7a, 0xac, - 0x5d, 0xf8, 0x01, 0x75, 0x0c, 0x15, 0x20, 0x3a, 0x7a, 0x4f, 0xda, 0x8e, 0xb0, 0xc2, 0x3d, 0x57, - 0x5c, 0x3f, 0x88, 0x11, 0x30, 0x2e, 0xf1, 0x19, 0xdf, 0x64, 0x79, 0x13, 0x6a, 0x3e, 0x0d, 0x02, - 0xcb, 0xe9, 0x88, 0xf5, 0x46, 0x5d, 0xf4, 0x95, 0xb6, 0x4c, 0xc3, 0x90, 0x4a, 0x7e, 0x02, 0xea, - 0xdc, 0xe5, 0xb4, 0xec, 0x75, 0xfc, 0xb9, 0x3a, 0x0f, 0x17, 0x9b, 0x12, 0x01, 0x70, 0x32, 0x11, - 0x23, 0x3a, 0xf9, 0x22, 0x4c, 0xee, 0xf1, 0xee, 0x2b, 0xf7, 0xdd, 0x0b, 0x1b, 0x17, 0xd7, 0xd6, - 0x5a, 0xb1, 0x74, 0x4c, 0x70, 0x91, 0x25, 0x00, 0x1a, 0xfa, 0xe5, 0xd2, 0xf6, 0xac, 0xc8, 0x63, - 0x87, 0x31, 0x2e, 0xf2, 0x12, 0x94, 0x02, 0xdb, 0xe7, 0x36, 0xac, 0x5a, 0xb4, 0x04, 0xdd, 0xd9, - 0x6c, 0x23, 0x4b, 0xd7, 0xfe, 0xb0, 0x00, 0x33, 0xa9, 0xed, 0x48, 0x2c, 0x4b, 0xdf, 0xb3, 0xe5, - 0x30, 0x12, 0x66, 0xd9, 0xc5, 0x4d, 0x64, 0xe9, 0xe4, 0x3d, 0xa9, 0x96, 0x17, 0x73, 0x1e, 0x31, - 0x72, 0x57, 0x0f, 0x7c, 0xa6, 0x87, 0x0f, 0x68, 0xe4, 0xdc, 0xcd, 0x17, 0x95, 0x47, 0xce, 0x03, - 0x31, 0x37, 0x5f, 0x44, 0xc3, 0x04, 0x67, 0xca, 0xe0, 0x57, 0x3e, 0x8b, 0xc1, 0x4f, 0xfb, 0xd5, - 0x62, 0xac, 0x06, 0xa4, 0x66, 0xff, 0x84, 0x1a, 0x78, 0x99, 0x4d, 0xa0, 0xe1, 0xe4, 0x5e, 0x8f, - 0xcf, 0x7f, 0x7c, 0x32, 0x96, 0x54, 0xf2, 0xb6, 0xa8, 0xfb, 0x52, 0xce, 0x8d, 0xdc, 0x3b, 0x9b, - 0x6d, 0x11, 0x5d, 0xa5, 0xfe, 0x5a, 0xf8, 0x0b, 0xca, 0x17, 0xf4, 0x0b, 0xb4, 0x7f, 0x56, 0x82, - 0xc6, 0x5b, 0xee, 0xde, 0x27, 0x24, 0x82, 0x3a, 0x7b, 0x9a, 0x2a, 0x7e, 0x8c, 0xd3, 0xd4, 0x2e, - 0xbc, 0x18, 0x04, 0x76, 0x9b, 0x1a, 0xae, 0x63, 0xfa, 0xcb, 0xfb, 0x01, 0xf5, 0xd6, 0x2c, 0xc7, - 0xf2, 0x0f, 0xa8, 0x29, 0xdd, 0x49, 0x9f, 0x39, 0x3d, 0x69, 0xbe, 0xb8, 0xb3, 0xb3, 0x99, 0xc5, - 0x82, 0xc3, 0xf2, 0xf2, 0x61, 0x43, 0xec, 0x1d, 0xe5, 0x7b, 0xab, 0x64, 0xcc, 0x8d, 0x18, 0x36, - 0x62, 0xe9, 0x98, 0xe0, 0xd2, 0xfe, 0x43, 0x11, 0xea, 0xe1, 0xe1, 0x11, 0xe4, 0xf3, 0x50, 0xdd, - 0xf3, 0xdc, 0x43, 0xea, 0x09, 0xcf, 0x9d, 0xdc, 0x5b, 0xd5, 0x12, 0x49, 0xa8, 0x68, 0xe4, 0x73, - 0x50, 0x09, 0xdc, 0x9e, 0x65, 0xa4, 0x0d, 0x6a, 0x3b, 0x2c, 0x11, 0x05, 0x8d, 0x77, 0x04, 0x1e, - 0x56, 0xc8, 0xbf, 0xaa, 0x16, 0xeb, 0x08, 0x3c, 0x15, 0x25, 0x55, 0x75, 0x84, 0xf2, 0xd8, 0x3b, - 0xc2, 0xcb, 0xa1, 0x0a, 0x58, 0x49, 0xf6, 0xc4, 0x94, 0xd2, 0xf6, 0x2e, 0x94, 0x7d, 0xdd, 0xb7, - 0xe5, 0xf4, 0x96, 0xe3, 0xbc, 0x86, 0xe5, 0xf6, 0xa6, 0x3c, 0xaf, 0x61, 0xb9, 0xbd, 0x89, 0x1c, - 0x54, 0xfb, 0xed, 0x12, 0x34, 0x44, 0xfd, 0x8a, 0xd1, 0x63, 0x9c, 0x35, 0xfc, 0x06, 0x0f, 0xb9, - 0xf0, 0xfb, 0x5d, 0xea, 0x71, 0x73, 0x94, 0x1c, 0x0c, 0xe3, 0x7e, 0x84, 0x88, 0x18, 0x86, 0x5d, - 0x44, 0x49, 0x3f, 0xda, 0x55, 0xcf, 0xa6, 0x0a, 0x7e, 0x00, 0x8a, 0xd4, 0x71, 0x65, 0x24, 0x65, - 0x38, 0x55, 0xdc, 0x89, 0xd1, 0x30, 0xc1, 0xa9, 0xfd, 0x8f, 0x22, 0xd4, 0x37, 0xad, 0x7d, 0x6a, - 0x1c, 0x1b, 0x36, 0x25, 0xdf, 0x80, 0x79, 0x93, 0xda, 0x94, 0xcd, 0x98, 0xeb, 0x9e, 0x6e, 0xd0, - 0x6d, 0xea, 0x59, 0xfc, 0x00, 0x27, 0xd6, 0x07, 0x65, 0x80, 0xeb, 0xf5, 0xd3, 0x93, 0xe6, 0xfc, - 0xea, 0x50, 0x2e, 0x7c, 0x0c, 0x02, 0xd9, 0x80, 0x49, 0x93, 0xfa, 0x96, 0x47, 0xcd, 0xed, 0xd8, - 0x82, 0xe8, 0xf3, 0xaa, 0x9c, 0xab, 0x31, 0xda, 0xa3, 0x93, 0xe6, 0x94, 0x32, 0x84, 0x8a, 0x95, - 0x51, 0x22, 0x2b, 0x1b, 0x5a, 0x7a, 0x7a, 0xdf, 0xa7, 0x19, 0xe5, 0x2c, 0xf1, 0x72, 0xf2, 0xa1, - 0x65, 0x3b, 0x9b, 0x05, 0x87, 0xe5, 0x25, 0x7b, 0x30, 0xc7, 0xcb, 0x9f, 0x85, 0x5b, 0xe6, 0xb8, - 0x2f, 0x9f, 0x9e, 0x34, 0xb5, 0x55, 0xda, 0xf3, 0xa8, 0xa1, 0x07, 0xd4, 0x5c, 0x1d, 0xc2, 0x8d, - 0x43, 0x71, 0xb4, 0x0a, 0x94, 0x36, 0xdd, 0x8e, 0xf6, 0xdd, 0x12, 0x84, 0x27, 0x8a, 0x91, 0x3f, - 0x5b, 0x80, 0x86, 0xee, 0x38, 0x6e, 0x20, 0x4f, 0xeb, 0x12, 0xd1, 0x04, 0x98, 0xfb, 0xe0, 0xb2, - 0x85, 0xe5, 0x08, 0x54, 0x38, 0xa2, 0x43, 0xe7, 0x78, 0x8c, 0x82, 0x71, 0xd9, 0xa4, 0x9f, 0xf2, - 0x8d, 0x6f, 0xe5, 0x2f, 0xc5, 0x19, 0x3c, 0xe1, 0xf3, 0x5f, 0x85, 0xd9, 0x74, 0x61, 0xcf, 0xe3, - 0xda, 0xca, 0x15, 0x64, 0x50, 0x04, 0x88, 0xe2, 0x63, 0x9e, 0x82, 0x41, 0xce, 0x4a, 0x18, 0xe4, - 0x46, 0x3f, 0xd6, 0x21, 0x2a, 0xf4, 0x50, 0x23, 0xdc, 0x37, 0x53, 0x46, 0xb8, 0x8d, 0x71, 0x08, - 0x7b, 0xbc, 0xe1, 0x6d, 0x0f, 0x2e, 0x45, 0xbc, 0xd1, 0xe8, 0x72, 0x27, 0xd5, 0xfb, 0x85, 0x5e, - 0xf9, 0x85, 0x21, 0xbd, 0x7f, 0x26, 0x16, 0xb0, 0x34, 0xd8, 0xff, 0xb5, 0xbf, 0x59, 0x80, 0xd9, - 0xb8, 0x10, 0xbe, 0x07, 0xfd, 0x4b, 0x30, 0xe5, 0x51, 0xdd, 0x6c, 0xe9, 0x81, 0x71, 0xc0, 0x43, - 0xe3, 0x0b, 0x3c, 0x96, 0x9d, 0xef, 0x96, 0xc3, 0x38, 0x01, 0x93, 0x7c, 0x44, 0x87, 0x06, 0x4b, - 0xd8, 0xb1, 0xba, 0xd4, 0xed, 0x07, 0x23, 0x5a, 0x99, 0xf9, 0x02, 0x0f, 0x23, 0x18, 0x8c, 0x63, - 0x6a, 0x1f, 0x15, 0x60, 0x3a, 0x5e, 0xe0, 0x0b, 0xb7, 0x40, 0x1e, 0x24, 0x2d, 0x90, 0x2b, 0x63, - 0xf8, 0xef, 0x43, 0xac, 0x8e, 0xdf, 0x6e, 0xc4, 0x3f, 0x8d, 0x5b, 0x1a, 0xe3, 0xc6, 0x95, 0xc2, - 0x63, 0x8d, 0x2b, 0x9f, 0xfc, 0x83, 0xaa, 0x86, 0xad, 0x0a, 0xca, 0xcf, 0xf0, 0xaa, 0xe0, 0xe3, - 0x3c, 0xed, 0x2a, 0x76, 0x62, 0xd3, 0x44, 0x8e, 0x13, 0x9b, 0xba, 0xe1, 0x89, 0x4d, 0xd5, 0xb1, - 0x0d, 0x6c, 0x67, 0x39, 0xb5, 0xa9, 0xf6, 0x54, 0x4f, 0x6d, 0xaa, 0x5f, 0xd4, 0xa9, 0x4d, 0x90, - 0xf7, 0xd4, 0xa6, 0xef, 0x14, 0x60, 0xda, 0x4c, 0xec, 0x30, 0x96, 0x7b, 0xfb, 0x47, 0x9f, 0xce, - 0x92, 0x1b, 0x96, 0xc5, 0x16, 0xb3, 0x64, 0x1a, 0xa6, 0x44, 0x66, 0x9d, 0x95, 0x34, 0xf9, 0xb1, - 0x9c, 0x95, 0x44, 0x7e, 0x09, 0xea, 0xb6, 0x9a, 0xeb, 0xe4, 0x09, 0x92, 0x9b, 0x63, 0x69, 0x92, - 0x12, 0x33, 0xda, 0xc5, 0x10, 0x26, 0x61, 0x24, 0x51, 0xfb, 0xfd, 0x6a, 0x7c, 0x42, 0x7c, 0xda, - 0x3e, 0x8e, 0xd7, 0x92, 0x3e, 0x8e, 0x1b, 0x69, 0x1f, 0xc7, 0xc0, 0x6c, 0x2e, 0xfd, 0x1c, 0x3f, - 0x19, 0x9b, 0x27, 0x4a, 0xfc, 0x90, 0xa6, 0xb0, 0xc9, 0x65, 0xcc, 0x15, 0xcb, 0x30, 0x23, 0x95, - 0x00, 0x45, 0xe4, 0x83, 0xec, 0x54, 0x14, 0x95, 0xb6, 0x9a, 0x24, 0x63, 0x9a, 0x9f, 0x09, 0xf4, - 0xd5, 0x59, 0xbd, 0x62, 0xc5, 0x16, 0xb5, 0x71, 0x75, 0x8e, 0x6e, 0xc8, 0xc1, 0x56, 0x77, 0x1e, - 0xd5, 0x7d, 0xe9, 0xa9, 0x88, 0xad, 0xee, 0x90, 0xa7, 0xa2, 0xa4, 0xc6, 0xdd, 0x35, 0xd5, 0x27, - 0xb8, 0x6b, 0x74, 0x68, 0xd8, 0xba, 0x1f, 0x88, 0xc6, 0x64, 0xca, 0xd1, 0xe4, 0x8f, 0x9d, 0x6d, - 0xde, 0x67, 0xba, 0x44, 0xa4, 0xc0, 0x6f, 0x46, 0x30, 0x18, 0xc7, 0x24, 0x26, 0x4c, 0xb2, 0x57, - 0x3e, 0xb2, 0x98, 0xcb, 0x81, 0x3c, 0xd1, 0xee, 0x3c, 0x32, 0xc2, 0xa5, 0xe3, 0x66, 0x0c, 0x07, - 0x13, 0xa8, 0x43, 0x3c, 0x3a, 0x30, 0x8a, 0x47, 0x87, 0xfc, 0xac, 0x50, 0xdc, 0x8e, 0xc3, 0xdf, - 0xda, 0xe0, 0xbf, 0x35, 0x8c, 0x68, 0xc5, 0x38, 0x11, 0x93, 0xbc, 0xac, 0x55, 0xf4, 0x65, 0x35, - 0xa8, 0xec, 0x93, 0xc9, 0x56, 0xb1, 0x9b, 0x24, 0x63, 0x9a, 0x9f, 0x6c, 0xc3, 0xe5, 0x30, 0x29, - 0x5e, 0x8c, 0x29, 0x8e, 0x13, 0x86, 0x18, 0xee, 0x66, 0xf0, 0x60, 0x66, 0x4e, 0xbe, 0x67, 0xa7, - 0xef, 0x79, 0xd4, 0x09, 0x6e, 0xeb, 0xfe, 0x81, 0x8c, 0x55, 0x8c, 0xf6, 0xec, 0x44, 0x24, 0x8c, - 0xf3, 0x91, 0x25, 0x00, 0x01, 0xc7, 0x73, 0xcd, 0x24, 0xc3, 0x81, 0x77, 0x43, 0x0a, 0xc6, 0xb8, - 0xb4, 0xef, 0xd4, 0xa1, 0x71, 0x57, 0x0f, 0xac, 0x23, 0xca, 0xdd, 0xaf, 0x17, 0xe3, 0x03, 0xfb, - 0x2b, 0x05, 0xb8, 0x92, 0x8c, 0xb1, 0xbd, 0x40, 0x47, 0x18, 0x3f, 0xe3, 0x09, 0x33, 0xa5, 0xe1, - 0x90, 0x52, 0x70, 0x97, 0xd8, 0x40, 0xc8, 0xee, 0x45, 0xbb, 0xc4, 0xda, 0xc3, 0x04, 0xe2, 0xf0, - 0xb2, 0x7c, 0x52, 0x5c, 0x62, 0xcf, 0xf6, 0xa1, 0xa4, 0x29, 0x87, 0x5d, 0xf5, 0x99, 0x71, 0xd8, - 0xd5, 0x9e, 0x09, 0xad, 0xbf, 0x17, 0x73, 0xd8, 0xd5, 0x73, 0x06, 0x8e, 0xc9, 0x6d, 0x29, 0x02, - 0x6d, 0x98, 0xe3, 0x8f, 0x9f, 0x28, 0xa1, 0x1c, 0x29, 0x4c, 0x59, 0xde, 0xd3, 0x7d, 0xcb, 0x90, - 0x6a, 0x47, 0x8e, 0x43, 0x98, 0xd5, 0xe1, 0x8c, 0x22, 0xbe, 0x84, 0xbf, 0xa2, 0xc0, 0x8e, 0xce, - 0xa2, 0x2c, 0xe6, 0x3a, 0x8b, 0x92, 0xac, 0x40, 0xd9, 0x39, 0xa4, 0xc7, 0xe7, 0x3b, 0x9b, 0x81, - 0x2f, 0x02, 0xef, 0xde, 0xa1, 0xc7, 0xc8, 0x33, 0x6b, 0xdf, 0x2b, 0x02, 0xb0, 0xcf, 0x3f, 0x9b, - 0xeb, 0xec, 0xc7, 0xa1, 0xea, 0xf7, 0xb9, 0x61, 0x48, 0x2a, 0x4c, 0x51, 0xb4, 0x9d, 0x48, 0x46, - 0x45, 0x27, 0x9f, 0x83, 0xca, 0x37, 0xfb, 0xb4, 0xaf, 0xe2, 0x40, 0xc2, 0x75, 0xc3, 0xd7, 0x58, - 0x22, 0x0a, 0xda, 0xc5, 0x99, 0xb7, 0x95, 0x8b, 0xad, 0x72, 0x51, 0x2e, 0xb6, 0x3a, 0x54, 0xef, - 0xba, 0x3c, 0x78, 0x57, 0xfb, 0xaf, 0x45, 0x80, 0x28, 0x38, 0x92, 0xfc, 0x7a, 0x01, 0x5e, 0x08, - 0x3b, 0x5c, 0x20, 0x96, 0x7f, 0xfc, 0xdc, 0xf3, 0xdc, 0xee, 0xb6, 0xac, 0xce, 0xce, 0x47, 0xa0, - 0xed, 0x2c, 0x71, 0x98, 0x5d, 0x0a, 0x82, 0x50, 0xa3, 0xdd, 0x5e, 0x70, 0xbc, 0x6a, 0x79, 0xb2, - 0x05, 0x66, 0xc6, 0xe0, 0xde, 0x92, 0x3c, 0x22, 0xab, 0xb4, 0x51, 0xf0, 0x4e, 0xa4, 0x28, 0x18, - 0xe2, 0x90, 0x03, 0xa8, 0x39, 0xee, 0x7b, 0x3e, 0xab, 0x0e, 0xd9, 0x1c, 0xdf, 0x1c, 0xbd, 0xca, - 0x45, 0xb5, 0x0a, 0xb7, 0x8b, 0x7c, 0xc1, 0xaa, 0x23, 0x2b, 0xfb, 0xd7, 0x8a, 0x70, 0x29, 0xa3, - 0x1e, 0xc8, 0x9b, 0x30, 0x2b, 0xe3, 0x50, 0xa3, 0x0b, 0x00, 0x0a, 0xd1, 0x05, 0x00, 0xed, 0x14, - 0x0d, 0x07, 0xb8, 0xc9, 0x7b, 0x00, 0xba, 0x61, 0x50, 0xdf, 0xdf, 0x72, 0x4d, 0xb5, 0x1e, 0x78, - 0x83, 0xa9, 0x2f, 0xcb, 0x61, 0xea, 0xa3, 0x93, 0xe6, 0x4f, 0x65, 0x85, 0x96, 0xa7, 0xea, 0x39, - 0xca, 0x80, 0x31, 0x48, 0xf2, 0x0d, 0x00, 0x61, 0x03, 0x08, 0x4f, 0xbf, 0x78, 0x82, 0xe1, 0x6c, - 0x41, 0x1d, 0xae, 0xb6, 0xf0, 0xb5, 0xbe, 0xee, 0x04, 0x56, 0x70, 0x2c, 0x0e, 0x1b, 0xba, 0x1f, - 0xa2, 0x60, 0x0c, 0x51, 0xfb, 0xc7, 0x45, 0xa8, 0x29, 0xd7, 0xc3, 0x53, 0xb0, 0x05, 0x77, 0x12, - 0xb6, 0xe0, 0x31, 0x05, 0x93, 0x67, 0x59, 0x82, 0xdd, 0x94, 0x25, 0x78, 0x3d, 0xbf, 0xa8, 0xc7, - 0xdb, 0x81, 0x7f, 0xab, 0x08, 0xd3, 0x8a, 0x35, 0xaf, 0x85, 0xf6, 0x2b, 0x30, 0x23, 0x82, 0x40, - 0xb6, 0xf4, 0x87, 0xe2, 0xdc, 0x25, 0x5e, 0x61, 0x65, 0x11, 0xbf, 0xdd, 0x4a, 0x92, 0x30, 0xcd, - 0xcb, 0x9a, 0xb5, 0x48, 0xda, 0x65, 0x8b, 0x30, 0xe1, 0x36, 0x16, 0xeb, 0x4d, 0xde, 0xac, 0x5b, - 0x29, 0x1a, 0x0e, 0x70, 0xa7, 0x4d, 0xc4, 0xe5, 0x0b, 0x30, 0x11, 0xff, 0xdb, 0x02, 0x4c, 0x46, - 0xf5, 0x75, 0xe1, 0x06, 0xe2, 0xfd, 0xa4, 0x81, 0x78, 0x39, 0x77, 0x73, 0x18, 0x62, 0x1e, 0xfe, - 0x0b, 0x55, 0x48, 0xec, 0x69, 0x20, 0x7b, 0x30, 0x6f, 0x65, 0x46, 0x66, 0xc6, 0x46, 0x9b, 0x70, - 0x93, 0xfe, 0xc6, 0x50, 0x4e, 0x7c, 0x0c, 0x0a, 0xe9, 0x43, 0xed, 0x88, 0x7a, 0x81, 0x65, 0x50, - 0xf5, 0x7d, 0xeb, 0xb9, 0x55, 0x32, 0x69, 0x04, 0x0f, 0xeb, 0xf4, 0xbe, 0x14, 0x80, 0xa1, 0x28, - 0xb2, 0x07, 0x15, 0x6a, 0x76, 0xa8, 0x3a, 0x09, 0x2b, 0xe7, 0xc9, 0xc4, 0x61, 0x7d, 0xb2, 0x37, - 0x1f, 0x05, 0x34, 0xf1, 0xe3, 0x86, 0xa6, 0x72, 0x4e, 0x05, 0xeb, 0x8c, 0xe6, 0x25, 0x72, 0x18, - 0x5a, 0x5b, 0x2b, 0x63, 0x1a, 0x3c, 0x1e, 0x63, 0x6b, 0xf5, 0xa1, 0xfe, 0x40, 0x0f, 0xa8, 0xd7, - 0xd5, 0xbd, 0x43, 0xb9, 0xda, 0x18, 0xfd, 0x0b, 0xdf, 0x56, 0x48, 0xd1, 0x17, 0x86, 0x49, 0x18, - 0xc9, 0x21, 0x2e, 0xd4, 0x03, 0xa9, 0x3e, 0x2b, 0x93, 0xf2, 0xe8, 0x42, 0x95, 0x22, 0xee, 0xcb, - 0xbd, 0x0d, 0xea, 0x15, 0x23, 0x19, 0xe4, 0x28, 0x71, 0x8c, 0xbd, 0xb8, 0xbc, 0xa0, 0x95, 0xc3, - 0x35, 0x21, 0xa1, 0xa2, 0xe9, 0x26, 0xfb, 0x38, 0x7c, 0xed, 0x7f, 0x55, 0xa2, 0x61, 0xf9, 0x69, - 0xdb, 0x09, 0xbf, 0x98, 0xb4, 0x13, 0x5e, 0x4f, 0xdb, 0x09, 0x53, 0x3e, 0xff, 0xf3, 0x47, 0x43, - 0xa7, 0xcc, 0x6b, 0xe5, 0x0b, 0x30, 0xaf, 0xbd, 0x02, 0x8d, 0x23, 0x3e, 0x12, 0x88, 0x63, 0xb5, - 0x2a, 0x7c, 0x1a, 0xe1, 0x23, 0xfb, 0xfd, 0x28, 0x19, 0xe3, 0x3c, 0x2c, 0x8b, 0xbc, 0xb8, 0x27, - 0x3c, 0xc9, 0x5a, 0x66, 0x69, 0x47, 0xc9, 0x18, 0xe7, 0xe1, 0x81, 0x94, 0x96, 0x73, 0x28, 0x32, - 0x54, 0x79, 0x06, 0x11, 0x48, 0xa9, 0x12, 0x31, 0xa2, 0x93, 0x9b, 0x50, 0xeb, 0x9b, 0xfb, 0x82, - 0xb7, 0xc6, 0x79, 0xb9, 0x86, 0xb9, 0xbb, 0xba, 0x26, 0x8f, 0xf9, 0x52, 0x54, 0x56, 0x92, 0xae, - 0xde, 0x53, 0x04, 0xbe, 0x36, 0x94, 0x25, 0xd9, 0x8a, 0x92, 0x31, 0xce, 0x43, 0x7e, 0x06, 0xa6, - 0x3d, 0x6a, 0xf6, 0x0d, 0x1a, 0xe6, 0x02, 0x9e, 0x4b, 0x9e, 0x7f, 0x1a, 0xa7, 0x60, 0x8a, 0x73, - 0x88, 0x91, 0xb0, 0x31, 0x92, 0x91, 0xf0, 0xab, 0x30, 0x6d, 0x7a, 0xba, 0xe5, 0x50, 0xf3, 0x9e, - 0xc3, 0x03, 0x3b, 0x64, 0x38, 0x67, 0x68, 0xa0, 0x5f, 0x4d, 0x50, 0x31, 0xc5, 0xad, 0xfd, 0xf3, - 0x22, 0x54, 0xc4, 0xa9, 0xac, 0x1b, 0x70, 0xc9, 0x72, 0xac, 0xc0, 0xd2, 0xed, 0x55, 0x6a, 0xeb, - 0xc7, 0xf1, 0x00, 0x97, 0x4a, 0xeb, 0x45, 0xb6, 0xd0, 0xde, 0x18, 0x24, 0x63, 0x56, 0x1e, 0x56, - 0x39, 0x81, 0x98, 0xbe, 0x15, 0x8a, 0xb0, 0xa3, 0x89, 0x23, 0xc1, 0x13, 0x14, 0x4c, 0x71, 0x32, - 0x65, 0xa8, 0x37, 0x10, 0xb9, 0x52, 0x11, 0xca, 0x50, 0x32, 0x98, 0x24, 0xc9, 0xc7, 0x95, 0xf4, - 0x3e, 0x57, 0x88, 0xc3, 0x4d, 0x53, 0x32, 0x08, 0x4e, 0x28, 0xe9, 0x29, 0x1a, 0x0e, 0x70, 0x33, - 0x84, 0x7d, 0xdd, 0xb2, 0xfb, 0x1e, 0x8d, 0x10, 0x2a, 0x11, 0xc2, 0x5a, 0x8a, 0x86, 0x03, 0xdc, - 0xda, 0x7f, 0x2f, 0x00, 0x19, 0xdc, 0x06, 0x42, 0x0e, 0x60, 0xc2, 0xe1, 0xb6, 0xc8, 0xdc, 0x37, - 0x11, 0xc4, 0x4c, 0x9a, 0x62, 0x92, 0x90, 0x09, 0x12, 0x9f, 0x38, 0x50, 0xa3, 0x0f, 0x03, 0xea, - 0x39, 0xe1, 0xb6, 0xb0, 0xf1, 0xdc, 0x7a, 0x20, 0xd6, 0x66, 0x12, 0x19, 0x43, 0x19, 0xda, 0xef, - 0x15, 0xa1, 0x11, 0xe3, 0x7b, 0xd2, 0x12, 0x9f, 0x9f, 0x4c, 0x21, 0x4c, 0x80, 0xbb, 0x9e, 0x2d, - 0xc7, 0xbb, 0xd8, 0xc9, 0x14, 0x92, 0x84, 0x9b, 0x18, 0xe7, 0x23, 0x4b, 0x00, 0x5d, 0xdd, 0x0f, - 0xa8, 0xc7, 0x75, 0xa1, 0xd4, 0x79, 0x10, 0x5b, 0x21, 0x05, 0x63, 0x5c, 0xe4, 0x86, 0xbc, 0xb7, - 0xa2, 0x9c, 0x3c, 0xbf, 0x73, 0xc8, 0xa5, 0x14, 0x95, 0x31, 0x5c, 0x4a, 0x41, 0x3a, 0x30, 0xab, - 0x4a, 0xad, 0xa8, 0xe7, 0x3b, 0xdd, 0x51, 0x34, 0xd4, 0x14, 0x04, 0x0e, 0x80, 0x6a, 0xdf, 0x2b, - 0xc0, 0x54, 0xc2, 0x00, 0x25, 0x4e, 0xde, 0x54, 0x9b, 0x98, 0x12, 0x27, 0x6f, 0xc6, 0xf6, 0x1e, - 0xbd, 0x0c, 0x13, 0xa2, 0x82, 0xd2, 0xb1, 0xc9, 0xa2, 0x0a, 0x51, 0x52, 0xd9, 0xcc, 0x22, 0x4d, - 0xdc, 0xe9, 0x99, 0x45, 0xda, 0xc0, 0x51, 0xd1, 0x85, 0xe7, 0x48, 0x94, 0x4e, 0xd6, 0x74, 0xcc, - 0x73, 0x24, 0xd2, 0x31, 0xe4, 0xd0, 0xfe, 0x3e, 0x2f, 0x77, 0xe0, 0x1d, 0x87, 0x2b, 0xeb, 0x0e, - 0x54, 0x65, 0x3c, 0xaa, 0xec, 0x1a, 0x6f, 0xe6, 0xb0, 0x8a, 0x71, 0x1c, 0x19, 0x51, 0xa9, 0x1b, - 0x87, 0xf7, 0xf6, 0xf7, 0x51, 0xa1, 0x93, 0x5b, 0x50, 0x77, 0x1d, 0xd9, 0x83, 0xe5, 0xe7, 0x7f, - 0x81, 0xcd, 0x1c, 0xf7, 0x54, 0xe2, 0xa3, 0x93, 0xe6, 0x95, 0xf0, 0x25, 0x51, 0x48, 0x8c, 0x72, - 0x6a, 0x7f, 0xa6, 0x00, 0x2f, 0xa0, 0x6b, 0xdb, 0x96, 0xd3, 0x49, 0x7a, 0x3e, 0x89, 0x0d, 0xd3, - 0x5d, 0xfd, 0xe1, 0xae, 0xa3, 0x1f, 0xe9, 0x96, 0xad, 0xef, 0xd9, 0xf4, 0x89, 0x2b, 0xe3, 0x7e, - 0x60, 0xd9, 0x0b, 0xe2, 0x1e, 0xcf, 0x85, 0x0d, 0x27, 0xb8, 0xe7, 0xb5, 0x03, 0xcf, 0x72, 0x3a, - 0x62, 0x94, 0xdc, 0x4a, 0x60, 0x61, 0x0a, 0x5b, 0xfb, 0xfd, 0x12, 0xf0, 0x58, 0x47, 0xf2, 0x25, - 0xa8, 0x77, 0xa9, 0x71, 0xa0, 0x3b, 0x96, 0xaf, 0xce, 0x30, 0xbe, 0xca, 0xbe, 0x6b, 0x4b, 0x25, - 0x3e, 0x62, 0xbf, 0x62, 0xb9, 0xbd, 0xc9, 0xb7, 0x1d, 0x45, 0xbc, 0xc4, 0x80, 0x89, 0x8e, 0xef, - 0xeb, 0x3d, 0x2b, 0x77, 0x88, 0x89, 0x38, 0x33, 0x56, 0x0c, 0x47, 0xe2, 0x19, 0x25, 0x34, 0x31, - 0xa0, 0xd2, 0xb3, 0x75, 0xcb, 0xc9, 0x7d, 0xef, 0x1c, 0xfb, 0x82, 0x6d, 0x86, 0x24, 0x4c, 0x95, - 0xfc, 0x11, 0x05, 0x36, 0xe9, 0x43, 0xc3, 0x37, 0x3c, 0xbd, 0xeb, 0x1f, 0xe8, 0x4b, 0xaf, 0xbe, - 0x96, 0x5b, 0xf9, 0x8f, 0x44, 0x09, 0x5d, 0x64, 0x05, 0x97, 0xb7, 0xda, 0xb7, 0x97, 0x97, 0x5e, - 0x7d, 0x0d, 0xe3, 0x72, 0xe2, 0x62, 0x5f, 0x7d, 0x65, 0x49, 0x8e, 0x20, 0x63, 0x17, 0xfb, 0xea, - 0x2b, 0x4b, 0x18, 0x97, 0xa3, 0xfd, 0xef, 0x02, 0xd4, 0x43, 0x5e, 0xb2, 0x0b, 0xc0, 0xc6, 0x32, - 0x79, 0xca, 0xeb, 0xb9, 0xee, 0xe8, 0xe1, 0xd6, 0x9e, 0xdd, 0x30, 0x33, 0xc6, 0x80, 0x32, 0x8e, - 0xc1, 0x2d, 0x8e, 0xfb, 0x18, 0xdc, 0x45, 0xa8, 0x1f, 0xe8, 0x8e, 0xe9, 0x1f, 0xe8, 0x87, 0x54, - 0x86, 0x88, 0x87, 0x4b, 0x91, 0xdb, 0x8a, 0x80, 0x11, 0x8f, 0xf6, 0x0f, 0x27, 0x40, 0xc4, 0x85, - 0xb0, 0x41, 0xc7, 0xb4, 0x7c, 0xb1, 0x91, 0xa3, 0xc0, 0x73, 0x86, 0x83, 0xce, 0xaa, 0x4c, 0xc7, - 0x90, 0x83, 0x5c, 0x85, 0x52, 0xd7, 0x72, 0xa4, 0x06, 0xc2, 0x0d, 0xb9, 0x5b, 0x96, 0x83, 0x2c, - 0x8d, 0x93, 0xf4, 0x87, 0x52, 0xc3, 0x10, 0x24, 0xfd, 0x21, 0xb2, 0x34, 0xf2, 0x15, 0x98, 0xb1, - 0x5d, 0xf7, 0x90, 0x0d, 0x1f, 0xf1, 0x50, 0xd7, 0x29, 0x61, 0x5a, 0xd9, 0x4c, 0x92, 0x30, 0xcd, - 0x4b, 0x76, 0xe1, 0xc5, 0x0f, 0xa8, 0xe7, 0xca, 0xf1, 0xb2, 0x6d, 0x53, 0xda, 0x53, 0x30, 0x42, - 0x35, 0xe6, 0x91, 0xb8, 0x3f, 0x9f, 0xcd, 0x82, 0xc3, 0xf2, 0xf2, 0xbd, 0x03, 0xba, 0xd7, 0xa1, - 0xc1, 0xb6, 0xe7, 0x32, 0xdd, 0xc5, 0x72, 0x3a, 0x0a, 0x76, 0x22, 0x82, 0xdd, 0xc9, 0x66, 0xc1, - 0x61, 0x79, 0xc9, 0x3b, 0x30, 0x27, 0x48, 0x42, 0x6d, 0x59, 0x16, 0xc3, 0x8c, 0x65, 0xab, 0xeb, - 0x5a, 0xa7, 0x84, 0xbf, 0x6c, 0x67, 0x08, 0x0f, 0x0e, 0xcd, 0x4d, 0xde, 0x82, 0x59, 0xe5, 0x2d, - 0xdd, 0xa6, 0x5e, 0x3b, 0x8c, 0x15, 0x9a, 0x52, 0x21, 0xd3, 0x2a, 0x64, 0x18, 0x53, 0x5c, 0x38, - 0x90, 0x8f, 0x20, 0x5c, 0xe1, 0x01, 0x41, 0xbb, 0xbd, 0x15, 0xd7, 0xb5, 0x4d, 0xf7, 0x81, 0xa3, - 0xbe, 0x5d, 0x28, 0xec, 0xdc, 0x41, 0xda, 0xce, 0xe4, 0xc0, 0x21, 0x39, 0xd9, 0x97, 0x73, 0xca, - 0xaa, 0xfb, 0xc0, 0x49, 0xa3, 0x42, 0xf4, 0xe5, 0xed, 0x21, 0x3c, 0x38, 0x34, 0x37, 0x59, 0x03, - 0x92, 0xfe, 0x82, 0xdd, 0x9e, 0x74, 0xe1, 0x5f, 0x11, 0x07, 0x36, 0xa5, 0xa9, 0x98, 0x91, 0x83, - 0x6c, 0xc2, 0xe5, 0x74, 0x2a, 0x13, 0x27, 0xbd, 0xf9, 0xfc, 0xa8, 0x66, 0xcc, 0xa0, 0x63, 0x66, - 0x2e, 0xed, 0x1f, 0x15, 0x61, 0x2a, 0x71, 0xc2, 0xc7, 0x33, 0x77, 0x92, 0x02, 0x5b, 0x3c, 0x74, - 0xfd, 0xce, 0xc6, 0xea, 0x6d, 0xaa, 0x9b, 0xd4, 0x53, 0x1b, 0x48, 0xea, 0x72, 0x5a, 0x4c, 0x50, - 0x30, 0xc5, 0x49, 0xf6, 0xa1, 0x22, 0xfc, 0x04, 0x79, 0x6f, 0x7b, 0x52, 0x75, 0xc4, 0x9d, 0x05, - 0xf2, 0x8a, 0x34, 0xd7, 0xa3, 0x28, 0xe0, 0xb5, 0x00, 0x26, 0xe3, 0x1c, 0x6c, 0x20, 0x89, 0xd4, - 0xde, 0x6a, 0x42, 0xe5, 0xdd, 0x80, 0x52, 0x10, 0x8c, 0x7a, 0x46, 0x83, 0xf0, 0x3b, 0xed, 0x6c, - 0x22, 0xc3, 0xd0, 0xf6, 0xd9, 0xbf, 0xf3, 0x7d, 0xcb, 0x75, 0xe4, 0x81, 0xfd, 0xbb, 0x50, 0x95, - 0xab, 0xa7, 0x11, 0xcf, 0x98, 0xe0, 0xba, 0x92, 0x32, 0xbb, 0x2a, 0x2c, 0xed, 0xdf, 0x15, 0xa1, - 0x1e, 0x9a, 0x49, 0xce, 0x70, 0x10, 0xbe, 0x0b, 0xf5, 0x30, 0xa0, 0x31, 0xf7, 0x55, 0xb6, 0x51, - 0x9c, 0x1d, 0x5f, 0xd9, 0x87, 0xaf, 0x18, 0xc9, 0x88, 0x07, 0x4b, 0x96, 0x72, 0x04, 0x4b, 0xf6, - 0xa0, 0x1a, 0x78, 0x56, 0xa7, 0x23, 0x57, 0x09, 0x79, 0xa2, 0x25, 0xc3, 0xea, 0xda, 0x11, 0x80, - 0xb2, 0x66, 0xc5, 0x0b, 0x2a, 0x31, 0xda, 0xfb, 0x30, 0x9b, 0xe6, 0xe4, 0x2a, 0xb4, 0x71, 0x40, - 0xcd, 0xbe, 0xad, 0xea, 0x38, 0x52, 0xa1, 0x65, 0x3a, 0x86, 0x1c, 0xe4, 0x26, 0xd4, 0xd8, 0x6f, - 0xfa, 0xc0, 0x75, 0x94, 0x1a, 0xcb, 0x57, 0x23, 0x3b, 0x32, 0x0d, 0x43, 0xaa, 0xf6, 0x5f, 0x4a, - 0x70, 0x35, 0x32, 0x76, 0x6d, 0xe9, 0x8e, 0xde, 0x39, 0xc3, 0xfd, 0xa5, 0x9f, 0xee, 0xda, 0x3b, - 0xef, 0x6d, 0x26, 0xa5, 0x67, 0xe0, 0x36, 0x93, 0xff, 0x57, 0x04, 0x1e, 0x7c, 0x4d, 0xbe, 0x05, - 0x93, 0x7a, 0xec, 0xea, 0x6a, 0xf9, 0x3b, 0x6f, 0xe5, 0xfe, 0x9d, 0x3c, 0xc6, 0x3b, 0x0c, 0x80, - 0x8b, 0xa7, 0x62, 0x42, 0x20, 0x71, 0xa1, 0xb6, 0xaf, 0xdb, 0x36, 0xd3, 0x85, 0x72, 0x3b, 0xef, - 0x12, 0xc2, 0x79, 0x33, 0x5f, 0x93, 0xd0, 0x18, 0x0a, 0x21, 0xdf, 0x29, 0xc0, 0x94, 0x17, 0x5f, - 0xae, 0xc9, 0x1f, 0x92, 0x27, 0xb4, 0x23, 0x86, 0x16, 0x0f, 0xb7, 0x8b, 0xaf, 0x09, 0x93, 0x32, - 0xb5, 0xff, 0x5c, 0x80, 0xa9, 0xb6, 0x6d, 0x99, 0x96, 0xd3, 0xb9, 0xc0, 0xcb, 0x54, 0xee, 0x41, - 0xc5, 0xb7, 0x2d, 0x93, 0x8e, 0x38, 0x9b, 0x88, 0x79, 0x8c, 0x01, 0xa0, 0xc0, 0x49, 0xde, 0xce, - 0x52, 0x3a, 0xc3, 0xed, 0x2c, 0x7f, 0x30, 0x01, 0x72, 0x1b, 0x01, 0xe9, 0x43, 0xbd, 0xa3, 0x2e, - 0x7d, 0x90, 0xdf, 0x78, 0x3b, 0xc7, 0x81, 0xa1, 0x89, 0xeb, 0x23, 0xc4, 0xd8, 0x1f, 0x26, 0x62, - 0x24, 0x89, 0xd0, 0xe4, 0x9d, 0xe9, 0xab, 0x39, 0xef, 0x4c, 0x17, 0xe2, 0x06, 0x6f, 0x4d, 0xd7, - 0xa1, 0x7c, 0x10, 0x04, 0x3d, 0xd9, 0x98, 0x46, 0xdf, 0x27, 0x12, 0x9d, 0x59, 0x25, 0x74, 0x22, - 0xf6, 0x8e, 0x1c, 0x9a, 0x89, 0x70, 0xf4, 0xf0, 0x66, 0xca, 0x95, 0x5c, 0x61, 0x24, 0x71, 0x11, - 0xec, 0x1d, 0x39, 0x34, 0xf9, 0x45, 0x68, 0x04, 0x9e, 0xee, 0xf8, 0xfb, 0xae, 0xd7, 0xa5, 0x9e, - 0x5c, 0xa3, 0xae, 0xe5, 0xb8, 0x36, 0x7c, 0x27, 0x42, 0x13, 0x26, 0xd9, 0x44, 0x12, 0xc6, 0xa5, - 0x91, 0x43, 0xa8, 0xf5, 0x4d, 0x51, 0x30, 0x69, 0x06, 0x5b, 0xce, 0x73, 0x13, 0x7c, 0x2c, 0x48, - 0x44, 0xbd, 0x61, 0x28, 0x20, 0x79, 0x09, 0x6b, 0x75, 0x5c, 0x97, 0xb0, 0xc6, 0x5b, 0x63, 0xd6, - 0x81, 0x3a, 0xa4, 0x2b, 0xf5, 0x5a, 0xa7, 0x23, 0x63, 0xdc, 0xd6, 0x72, 0xab, 0x9c, 0x42, 0x64, - 0x23, 0xd4, 0x8d, 0x9d, 0x0e, 0x2a, 0x19, 0x5a, 0x17, 0xa4, 0xef, 0x88, 0x18, 0x89, 0x8b, 0xa7, - 0xc4, 0xce, 0xc8, 0xc5, 0xb3, 0x8d, 0x07, 0xe1, 0x0d, 0x48, 0xb1, 0x83, 0xef, 0x33, 0x6f, 0x98, - 0xd2, 0xfe, 0x7d, 0x11, 0x4a, 0x3b, 0x9b, 0x6d, 0x71, 0x98, 0x2d, 0xbf, 0xca, 0x8e, 0xb6, 0x0f, - 0xad, 0xde, 0x7d, 0xea, 0x59, 0xfb, 0xc7, 0x72, 0xe9, 0x1d, 0x3b, 0xcc, 0x36, 0xcd, 0x81, 0x19, - 0xb9, 0xc8, 0xbb, 0x30, 0x69, 0xe8, 0x2b, 0xd4, 0x0b, 0x46, 0x31, 0x2c, 0xf0, 0xed, 0xec, 0x2b, - 0xcb, 0x51, 0x76, 0x4c, 0x80, 0x91, 0x5d, 0x00, 0x23, 0x82, 0x2e, 0x9d, 0xdb, 0x1c, 0x12, 0x03, - 0x8e, 0x01, 0x11, 0x84, 0xfa, 0x21, 0x63, 0xe5, 0xa8, 0xe5, 0xf3, 0xa0, 0xf2, 0x96, 0x73, 0x47, - 0xe5, 0xc5, 0x08, 0x46, 0x73, 0x60, 0x2a, 0x71, 0x1b, 0x15, 0xf9, 0x32, 0xd4, 0xdc, 0x5e, 0x6c, - 0x38, 0xad, 0xf3, 0x68, 0xda, 0xda, 0x3d, 0x99, 0xf6, 0xe8, 0xa4, 0x39, 0xb5, 0xe9, 0x76, 0x2c, - 0x43, 0x25, 0x60, 0xc8, 0x4e, 0x34, 0x98, 0xe0, 0xfb, 0x36, 0xd5, 0x5d, 0x54, 0x7c, 0xee, 0xe0, - 0xd7, 0xc5, 0xf8, 0x28, 0x29, 0xda, 0x2f, 0x97, 0x21, 0xf2, 0xb8, 0x12, 0x1f, 0x26, 0xc4, 0x9e, - 0x11, 0x39, 0x72, 0x5f, 0xe8, 0xf6, 0x14, 0x29, 0x8a, 0x74, 0xa0, 0xf4, 0xbe, 0xbb, 0x97, 0x7b, - 0xe0, 0x8e, 0x1d, 0x3e, 0x21, 0x6c, 0x65, 0xb1, 0x04, 0x64, 0x12, 0xc8, 0x5f, 0x2d, 0xc0, 0xf3, - 0x7e, 0x5a, 0xf5, 0x95, 0xcd, 0x01, 0xf3, 0xeb, 0xf8, 0x69, 0x65, 0x5a, 0x86, 0x3d, 0x0f, 0x23, - 0xe3, 0x60, 0x59, 0x58, 0xfd, 0x0b, 0x57, 0xa8, 0x6c, 0x4e, 0xeb, 0x39, 0xef, 0xdc, 0x4d, 0xd6, - 0x7f, 0x32, 0x0d, 0xa5, 0x28, 0xed, 0xdb, 0x45, 0x68, 0xc4, 0x46, 0xeb, 0xdc, 0x57, 0x9c, 0x3d, - 0x4c, 0x5d, 0x71, 0xb6, 0x3d, 0x7a, 0x64, 0x40, 0x54, 0xaa, 0x8b, 0xbe, 0xe5, 0xec, 0x9f, 0x16, - 0xa1, 0xb4, 0xbb, 0xba, 0x96, 0x5c, 0xb4, 0x16, 0x9e, 0xc2, 0xa2, 0xf5, 0x00, 0xaa, 0x7b, 0x7d, - 0xcb, 0x0e, 0x2c, 0x27, 0xf7, 0xf1, 0x38, 0xea, 0x46, 0x38, 0xe9, 0xeb, 0x10, 0xa8, 0xa8, 0xe0, - 0x49, 0x07, 0xaa, 0x1d, 0x71, 0x3e, 0x69, 0xee, 0x78, 0x49, 0x79, 0xce, 0xa9, 0x10, 0x24, 0x5f, - 0x50, 0xa1, 0x6b, 0xc7, 0x30, 0xb1, 0xbb, 0x2a, 0xd5, 0xfe, 0xa7, 0x5b, 0x9b, 0xda, 0x2f, 0x42, - 0xa8, 0x05, 0x3c, 0x7d, 0xe1, 0xff, 0xad, 0x00, 0x49, 0xc5, 0xe7, 0xe9, 0xb7, 0xa6, 0xc3, 0x74, - 0x6b, 0x5a, 0x1d, 0x47, 0xe7, 0xcb, 0x6e, 0x50, 0xda, 0xbf, 0x29, 0x40, 0x6a, 0xa3, 0x1f, 0x79, - 0x4d, 0x1e, 0x75, 0x97, 0x0c, 0x4c, 0x53, 0x47, 0xdd, 0x91, 0x24, 0x77, 0xec, 0xc8, 0xbb, 0x0f, - 0xd9, 0x72, 0x2d, 0xee, 0x40, 0x93, 0xc5, 0xbf, 0x3b, 0xfa, 0x72, 0x2d, 0xcb, 0x1d, 0x27, 0x83, - 0x27, 0xe3, 0x24, 0x4c, 0xca, 0xd5, 0xfe, 0x41, 0x11, 0x26, 0x9e, 0xda, 0xd9, 0x06, 0x34, 0x11, - 0xcf, 0xba, 0x92, 0x73, 0xb4, 0x1f, 0x1a, 0xcd, 0xda, 0x4d, 0x45, 0xb3, 0xe6, 0xbd, 0xca, 0xfd, - 0x09, 0xb1, 0xac, 0xff, 0xaa, 0x00, 0x72, 0xae, 0xd9, 0x70, 0xfc, 0x40, 0x77, 0x0c, 0x4a, 0x8c, - 0x70, 0x62, 0xcb, 0x1b, 0x34, 0x25, 0x03, 0x0b, 0x85, 0x2e, 0xc3, 0x9f, 0xd5, 0x44, 0x46, 0x7e, - 0x12, 0x6a, 0x07, 0xae, 0x1f, 0xf0, 0xc9, 0xab, 0x98, 0x34, 0x99, 0xdd, 0x96, 0xe9, 0x18, 0x72, - 0xa4, 0xdd, 0xd9, 0x95, 0xe1, 0xee, 0x6c, 0xed, 0x37, 0x8b, 0x30, 0xf9, 0x49, 0x39, 0x3c, 0x21, - 0x2b, 0xfa, 0xb7, 0x94, 0x33, 0xfa, 0xb7, 0x7c, 0x9e, 0xe8, 0x5f, 0xed, 0x07, 0x05, 0x80, 0xa7, - 0x76, 0x72, 0x83, 0x99, 0x0c, 0xcc, 0xcd, 0xdd, 0xae, 0xb2, 0xc3, 0x72, 0xff, 0x6e, 0x45, 0x7d, - 0x12, 0x0f, 0xca, 0xfd, 0xb0, 0x00, 0xd3, 0x7a, 0x22, 0xd0, 0x35, 0xb7, 0xbe, 0x9c, 0x8a, 0x9b, - 0x0d, 0xe3, 0xb4, 0x92, 0xe9, 0x98, 0x12, 0x4b, 0x5e, 0x8f, 0x4e, 0x59, 0xbf, 0x1b, 0x35, 0xfb, - 0x81, 0xe3, 0xd1, 0xb9, 0xee, 0x96, 0xe0, 0x7c, 0x42, 0x60, 0x71, 0x69, 0x2c, 0x81, 0xc5, 0xf1, - 0x2d, 0x93, 0xe5, 0xc7, 0x6e, 0x99, 0x3c, 0x82, 0xfa, 0xbe, 0xe7, 0x76, 0x79, 0xec, 0xae, 0xbc, - 0xc7, 0xfc, 0x56, 0x8e, 0x89, 0xb2, 0xbb, 0x67, 0x39, 0xd4, 0xe4, 0x71, 0xc1, 0xa1, 0xe1, 0x6a, - 0x4d, 0xe1, 0x63, 0x24, 0x8a, 0xdb, 0xfa, 0x5d, 0x21, 0x75, 0x62, 0x9c, 0x52, 0xc3, 0xb1, 0x64, - 0x47, 0xa0, 0xa3, 0x12, 0x93, 0x8c, 0xd7, 0xad, 0x3e, 0x9d, 0x78, 0x5d, 0xed, 0xcf, 0x57, 0xd5, - 0x00, 0xf6, 0xcc, 0x1d, 0xe8, 0xfb, 0xe9, 0x46, 0xf7, 0x0e, 0x1d, 0xd8, 0x85, 0x5e, 0x7b, 0x8a, - 0xbb, 0xd0, 0xeb, 0xe3, 0xd9, 0x85, 0x0e, 0xf9, 0x76, 0xa1, 0x37, 0xc6, 0xb4, 0x0b, 0x7d, 0x72, - 0x5c, 0xbb, 0xd0, 0xa7, 0x46, 0xda, 0x85, 0x3e, 0x7d, 0xa6, 0x5d, 0xe8, 0x27, 0x25, 0x48, 0x2d, - 0xc6, 0x3f, 0x75, 0xbc, 0xfd, 0x48, 0x39, 0xde, 0xbe, 0x5b, 0x84, 0x68, 0x20, 0x3e, 0x67, 0x60, - 0xd2, 0x3b, 0x50, 0xeb, 0xea, 0x0f, 0x79, 0xe0, 0x74, 0x9e, 0x7b, 0xb0, 0xb7, 0x24, 0x06, 0x86, - 0x68, 0xc4, 0x07, 0xb0, 0xc2, 0xbb, 0x28, 0x72, 0xbb, 0x30, 0xa2, 0x6b, 0x2d, 0x84, 0x91, 0x34, - 0x7a, 0xc7, 0x98, 0x18, 0xed, 0x5f, 0x16, 0x41, 0x5e, 0x5a, 0x42, 0x28, 0x54, 0xf6, 0xad, 0x87, - 0xd4, 0xcc, 0x1d, 0xee, 0xbc, 0xc6, 0x50, 0xe4, 0xcd, 0x28, 0xdc, 0x47, 0xc3, 0x13, 0x50, 0xa0, - 0x73, 0xe3, 0xbb, 0xf0, 0xb9, 0xc9, 0xfa, 0xcb, 0x61, 0x7c, 0x8f, 0xfb, 0xee, 0xa4, 0xf1, 0x5d, - 0x24, 0xa1, 0x92, 0x21, 0x6c, 0xfd, 0x3c, 0xfc, 0x22, 0xb7, 0x8b, 0x31, 0x11, 0xc6, 0xa1, 0x6c, - 0xfd, 0xbe, 0x38, 0x86, 0x42, 0xca, 0x68, 0xfd, 0xc2, 0xf7, 0x7f, 0x78, 0xfd, 0xb9, 0x1f, 0xfc, - 0xf0, 0xfa, 0x73, 0x1f, 0xfd, 0xf0, 0xfa, 0x73, 0xbf, 0x7c, 0x7a, 0xbd, 0xf0, 0xfd, 0xd3, 0xeb, - 0x85, 0x1f, 0x9c, 0x5e, 0x2f, 0x7c, 0x74, 0x7a, 0xbd, 0xf0, 0x1f, 0x4f, 0xaf, 0x17, 0xfe, 0xd2, - 0x7f, 0xba, 0xfe, 0xdc, 0xcf, 0x7f, 0x29, 0x2a, 0xc2, 0xa2, 0x2a, 0xc2, 0xa2, 0x12, 0xb8, 0xd8, - 0x3b, 0xec, 0x2c, 0xb2, 0x22, 0x44, 0x29, 0xaa, 0x08, 0xff, 0x3f, 0x00, 0x00, 0xff, 0xff, 0xa1, - 0x3f, 0x0d, 0xca, 0x09, 0xa0, 0x00, 0x00, + // 8292 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6f, 0x6c, 0x24, 0x47, + 0x76, 0x9f, 0xe6, 0xff, 0xcc, 0x1b, 0x92, 0x4b, 0xd5, 0xae, 0x56, 0x5c, 0xde, 0x6a, 0x67, 0xaf, + 0xcf, 0xa7, 0x5b, 0xc7, 0x67, 0x32, 0xa2, 0x4f, 0x3a, 0x9d, 0xed, 0x3b, 0x89, 0x43, 0x2e, 0x77, + 0xa9, 0x25, 0x77, 0x79, 0x6f, 0xc8, 0x95, 0xce, 0x8a, 0x4f, 0x69, 0x76, 0x17, 0x87, 0x2d, 0xf6, + 0x74, 0xcf, 0x75, 0xf7, 0x70, 0x97, 0x72, 0x8c, 0xb3, 0xef, 0x12, 0xe8, 0x82, 0x24, 0x48, 0xe0, + 0x4f, 0x06, 0x02, 0x27, 0x48, 0x10, 0xc0, 0x1f, 0x0c, 0xe7, 0x83, 0x91, 0xcb, 0x87, 0x00, 0xf9, + 0xe3, 0x20, 0x48, 0x2e, 0xff, 0x0f, 0x41, 0x80, 0x28, 0x1f, 0x42, 0xe4, 0x18, 0x04, 0x41, 0x02, + 0x24, 0x70, 0x62, 0x24, 0x76, 0x16, 0x41, 0x1c, 0xd4, 0xbf, 0xfe, 0x37, 0x3d, 0xbb, 0xe4, 0xf4, + 0x70, 0xb5, 0x72, 0xf4, 0x6d, 0xa6, 0xde, 0xab, 0xdf, 0xab, 0xae, 0xae, 0xae, 0x7a, 0xf5, 0xde, + 0xab, 0x57, 0x70, 0xab, 0x6b, 0x05, 0xfb, 0x83, 0xdd, 0x05, 0xc3, 0xed, 0x2d, 0x3a, 0x83, 0x9e, + 0xde, 0xf7, 0xdc, 0xf7, 0xf9, 0x8f, 0x3d, 0xdb, 0x7d, 0xb0, 0xd8, 0x3f, 0xe8, 0x2e, 0xea, 0x7d, + 0xcb, 0x8f, 0x4a, 0x0e, 0x5f, 0xd1, 0xed, 0xfe, 0xbe, 0xfe, 0xca, 0x62, 0x97, 0x3a, 0xd4, 0xd3, + 0x03, 0x6a, 0x2e, 0xf4, 0x3d, 0x37, 0x70, 0xc9, 0x97, 0x23, 0xa0, 0x05, 0x05, 0xb4, 0xa0, 0xaa, + 0x2d, 0xf4, 0x0f, 0xba, 0x0b, 0x0c, 0x28, 0x2a, 0x51, 0x40, 0xf3, 0x3f, 0x19, 0x6b, 0x41, 0xd7, + 0xed, 0xba, 0x8b, 0x1c, 0x6f, 0x77, 0xb0, 0xc7, 0xff, 0xf1, 0x3f, 0xfc, 0x97, 0x90, 0x33, 0xaf, + 0x1d, 0xbc, 0xee, 0x2f, 0x58, 0x2e, 0x6b, 0xd6, 0xa2, 0xe1, 0x7a, 0x74, 0xf1, 0x70, 0xa8, 0x2d, + 0xf3, 0x5f, 0x8a, 0x78, 0x7a, 0xba, 0xb1, 0x6f, 0x39, 0xd4, 0x3b, 0x52, 0xcf, 0xb2, 0xe8, 0x51, + 0xdf, 0x1d, 0x78, 0x06, 0x3d, 0x53, 0x2d, 0x7f, 0xb1, 0x47, 0x03, 0x3d, 0x4b, 0xd6, 0xe2, 0xa8, + 0x5a, 0xde, 0xc0, 0x09, 0xac, 0xde, 0xb0, 0x98, 0xd7, 0x9e, 0x54, 0xc1, 0x37, 0xf6, 0x69, 0x4f, + 0x1f, 0xaa, 0xf7, 0x53, 0xa3, 0xea, 0x0d, 0x02, 0xcb, 0x5e, 0xb4, 0x9c, 0xc0, 0x0f, 0xbc, 0x74, + 0x25, 0xed, 0xb7, 0x01, 0x2e, 0x2e, 0xef, 0xfa, 0x81, 0xa7, 0x1b, 0xc1, 0x96, 0x6b, 0x6e, 0xd3, + 0x5e, 0xdf, 0xd6, 0x03, 0x4a, 0x0e, 0xa0, 0xce, 0x1e, 0xc8, 0xd4, 0x03, 0x7d, 0xae, 0x70, 0xbd, + 0x70, 0xa3, 0xb9, 0xb4, 0xbc, 0x30, 0xe6, 0x0b, 0x5c, 0xd8, 0x94, 0x40, 0xed, 0xa9, 0x93, 0xe3, + 0x56, 0x5d, 0xfd, 0xc3, 0x50, 0x00, 0xf9, 0xd5, 0x02, 0x4c, 0x39, 0xae, 0x49, 0x3b, 0xd4, 0xa6, + 0x46, 0xe0, 0x7a, 0x73, 0xc5, 0xeb, 0xa5, 0x1b, 0xcd, 0xa5, 0x6f, 0x8e, 0x2d, 0x31, 0xe3, 0x89, + 0x16, 0xee, 0xc6, 0x04, 0xdc, 0x74, 0x02, 0xef, 0xa8, 0x7d, 0xe9, 0x07, 0xc7, 0xad, 0xe7, 0x4e, + 0x8e, 0x5b, 0x53, 0x71, 0x12, 0x26, 0x5a, 0x42, 0x76, 0xa0, 0x19, 0xb8, 0x36, 0xeb, 0x32, 0xcb, + 0x75, 0xfc, 0xb9, 0x12, 0x6f, 0xd8, 0xb5, 0x05, 0xd1, 0xd5, 0x4c, 0xfc, 0x02, 0x1b, 0x63, 0x0b, + 0x87, 0xaf, 0x2c, 0x6c, 0x87, 0x6c, 0xed, 0x8b, 0x12, 0xb8, 0x19, 0x95, 0xf9, 0x18, 0xc7, 0x21, + 0x14, 0x2e, 0xf8, 0xd4, 0x18, 0x78, 0x56, 0x70, 0xb4, 0xe2, 0x3a, 0x01, 0x7d, 0x18, 0xcc, 0x95, + 0x79, 0x2f, 0xbf, 0x9c, 0x05, 0xbd, 0xe5, 0x9a, 0x9d, 0x24, 0x77, 0xfb, 0xe2, 0xc9, 0x71, 0xeb, + 0x42, 0xaa, 0x10, 0xd3, 0x98, 0xc4, 0x81, 0x59, 0xab, 0xa7, 0x77, 0xe9, 0xd6, 0xc0, 0xb6, 0x3b, + 0xd4, 0xf0, 0x68, 0xe0, 0xcf, 0x55, 0xf8, 0x23, 0xdc, 0xc8, 0x92, 0xb3, 0xe1, 0x1a, 0xba, 0x7d, + 0x6f, 0xf7, 0x7d, 0x6a, 0x04, 0x48, 0xf7, 0xa8, 0x47, 0x1d, 0x83, 0xb6, 0xe7, 0xe4, 0xc3, 0xcc, + 0xae, 0xa7, 0x90, 0x70, 0x08, 0x9b, 0xdc, 0x82, 0xe7, 0xfb, 0x9e, 0xe5, 0xf2, 0x26, 0xd8, 0xba, + 0xef, 0xdf, 0xd5, 0x7b, 0x74, 0xae, 0x7a, 0xbd, 0x70, 0xa3, 0xd1, 0xbe, 0x22, 0x61, 0x9e, 0xdf, + 0x4a, 0x33, 0xe0, 0x70, 0x1d, 0x72, 0x03, 0xea, 0xaa, 0x70, 0xae, 0x76, 0xbd, 0x70, 0xa3, 0x22, + 0xc6, 0x8e, 0xaa, 0x8b, 0x21, 0x95, 0xac, 0x41, 0x5d, 0xdf, 0xdb, 0xb3, 0x1c, 0xc6, 0x59, 0xe7, + 0x5d, 0x78, 0x35, 0xeb, 0xd1, 0x96, 0x25, 0x8f, 0xc0, 0x51, 0xff, 0x30, 0xac, 0x4b, 0xde, 0x02, + 0xe2, 0x53, 0xef, 0xd0, 0x32, 0xe8, 0xb2, 0x61, 0xb8, 0x03, 0x27, 0xe0, 0x6d, 0x6f, 0xf0, 0xb6, + 0xcf, 0xcb, 0xb6, 0x93, 0xce, 0x10, 0x07, 0x66, 0xd4, 0x22, 0x6f, 0xc2, 0xac, 0xfc, 0x56, 0xa3, + 0x5e, 0x00, 0x8e, 0x74, 0x89, 0x75, 0x24, 0xa6, 0x68, 0x38, 0xc4, 0x4d, 0x4c, 0xb8, 0xaa, 0x0f, + 0x02, 0xb7, 0xc7, 0x20, 0x93, 0x42, 0xb7, 0xdd, 0x03, 0xea, 0xcc, 0x35, 0xaf, 0x17, 0x6e, 0xd4, + 0xdb, 0xd7, 0x4f, 0x8e, 0x5b, 0x57, 0x97, 0x1f, 0xc3, 0x87, 0x8f, 0x45, 0x21, 0xf7, 0xa0, 0x61, + 0x3a, 0xfe, 0x96, 0x6b, 0x5b, 0xc6, 0xd1, 0xdc, 0x14, 0x6f, 0xe0, 0x2b, 0xf2, 0x51, 0x1b, 0xab, + 0x77, 0x3b, 0x82, 0xf0, 0xe8, 0xb8, 0x75, 0x75, 0x78, 0x4a, 0x5d, 0x08, 0xe9, 0x18, 0x61, 0x90, + 0x4d, 0x0e, 0xb8, 0xe2, 0x3a, 0x7b, 0x56, 0x77, 0x6e, 0x9a, 0xbf, 0x8d, 0xeb, 0x23, 0x06, 0xf4, + 0xea, 0xdd, 0x8e, 0xe0, 0x6b, 0x4f, 0x4b, 0x71, 0xe2, 0x2f, 0x46, 0x08, 0xc4, 0x84, 0x19, 0x35, + 0x19, 0xaf, 0xd8, 0xba, 0xd5, 0xf3, 0xe7, 0x66, 0xf8, 0xe0, 0xfd, 0xb1, 0x11, 0x98, 0x18, 0x67, + 0x6e, 0x5f, 0x96, 0x8f, 0x32, 0x93, 0x28, 0xf6, 0x31, 0x85, 0x39, 0xff, 0x06, 0x3c, 0x3f, 0x34, + 0x37, 0x90, 0x59, 0x28, 0x1d, 0xd0, 0x23, 0x3e, 0xf5, 0x35, 0x90, 0xfd, 0x24, 0x97, 0xa0, 0x72, + 0xa8, 0xdb, 0x03, 0x3a, 0x57, 0xe4, 0x65, 0xe2, 0xcf, 0x4f, 0x17, 0x5f, 0x2f, 0x68, 0x7f, 0xb5, + 0x04, 0x53, 0x6a, 0xc6, 0xe9, 0x58, 0xce, 0x01, 0x79, 0x1b, 0x4a, 0xb6, 0xdb, 0x95, 0xf3, 0xe6, + 0xcf, 0x8e, 0x3d, 0x8b, 0x6d, 0xb8, 0xdd, 0x76, 0xed, 0xe4, 0xb8, 0x55, 0xda, 0x70, 0xbb, 0xc8, + 0x10, 0x89, 0x01, 0x95, 0x03, 0x7d, 0xef, 0x40, 0xe7, 0x6d, 0x68, 0x2e, 0xb5, 0xc7, 0x86, 0xbe, + 0xc3, 0x50, 0x58, 0x5b, 0xdb, 0x8d, 0x93, 0xe3, 0x56, 0x85, 0xff, 0x45, 0x81, 0x4d, 0x5c, 0x68, + 0xec, 0xda, 0xba, 0x71, 0xb0, 0xef, 0xda, 0x74, 0xae, 0x94, 0x53, 0x50, 0x5b, 0x21, 0x89, 0xd7, + 0x1c, 0xfe, 0xc5, 0x48, 0x06, 0x31, 0xa0, 0x3a, 0x30, 0x7d, 0xcb, 0x39, 0x90, 0x73, 0xe0, 0x1b, + 0x63, 0x4b, 0xdb, 0x59, 0xe5, 0xcf, 0x04, 0x27, 0xc7, 0xad, 0xaa, 0xf8, 0x8d, 0x12, 0x5a, 0xfb, + 0xfd, 0x29, 0x98, 0x51, 0x2f, 0xe9, 0x3e, 0xf5, 0x02, 0xfa, 0x90, 0x5c, 0x87, 0xb2, 0xc3, 0x3e, + 0x4d, 0xfe, 0x92, 0xdb, 0x53, 0x72, 0xb8, 0x94, 0xf9, 0x27, 0xc9, 0x29, 0xac, 0x65, 0x62, 0xa8, + 0xc8, 0x0e, 0x1f, 0xbf, 0x65, 0x1d, 0x0e, 0x23, 0x5a, 0x26, 0x7e, 0xa3, 0x84, 0x26, 0xef, 0x42, + 0x99, 0x3f, 0xbc, 0xe8, 0xea, 0xaf, 0x8e, 0x2f, 0x82, 0x3d, 0x7a, 0x9d, 0x3d, 0x01, 0x7f, 0x70, + 0x0e, 0xca, 0x86, 0xe2, 0xc0, 0xdc, 0x93, 0x1d, 0xfb, 0xb3, 0x39, 0x3a, 0x76, 0x4d, 0x0c, 0xc5, + 0x9d, 0xd5, 0x35, 0x64, 0x88, 0xe4, 0xcf, 0x17, 0xe0, 0x79, 0xc3, 0x75, 0x02, 0x9d, 0xe9, 0x19, + 0x6a, 0x91, 0x9d, 0xab, 0x70, 0x39, 0x6f, 0x8d, 0x2d, 0x67, 0x25, 0x8d, 0xd8, 0x7e, 0x81, 0xad, + 0x19, 0x43, 0xc5, 0x38, 0x2c, 0x9b, 0xfc, 0xc5, 0x02, 0xbc, 0xc0, 0xe6, 0xf2, 0x21, 0x66, 0xbe, + 0x02, 0x4d, 0xb6, 0x55, 0x57, 0x4e, 0x8e, 0x5b, 0x2f, 0xac, 0x67, 0x09, 0xc3, 0xec, 0x36, 0xb0, + 0xd6, 0x5d, 0xd4, 0x87, 0xd5, 0x12, 0xbe, 0xba, 0x35, 0x97, 0x36, 0x26, 0xa9, 0xea, 0xb4, 0x3f, + 0x23, 0x87, 0x72, 0x96, 0x66, 0x87, 0x59, 0xad, 0x20, 0x37, 0xa1, 0x76, 0xe8, 0xda, 0x83, 0x1e, + 0xf5, 0xe7, 0xea, 0x7c, 0x8a, 0x9d, 0xcf, 0x9a, 0x62, 0xef, 0x73, 0x96, 0xf6, 0x05, 0x09, 0x5f, + 0x13, 0xff, 0x7d, 0x54, 0x75, 0x89, 0x05, 0x55, 0xdb, 0xea, 0x59, 0x81, 0xcf, 0x17, 0xce, 0xe6, + 0xd2, 0xcd, 0xb1, 0x1f, 0x4b, 0x7c, 0xa2, 0x1b, 0x1c, 0x4c, 0x7c, 0x35, 0xe2, 0x37, 0x4a, 0x01, + 0x6c, 0x2a, 0xf4, 0x0d, 0xdd, 0x16, 0x0b, 0x6b, 0x73, 0xe9, 0x6b, 0xe3, 0x7f, 0x36, 0x0c, 0xa5, + 0x3d, 0x2d, 0x9f, 0xa9, 0xc2, 0xff, 0xa2, 0xc0, 0x26, 0x3f, 0x0f, 0x33, 0x89, 0xb7, 0xe9, 0xcf, + 0x35, 0x79, 0xef, 0xbc, 0x94, 0xd5, 0x3b, 0x21, 0x57, 0xb4, 0xf2, 0x24, 0x46, 0x88, 0x8f, 0x29, + 0x30, 0x72, 0x07, 0xea, 0xbe, 0x65, 0x52, 0x43, 0xf7, 0xfc, 0xb9, 0xa9, 0xd3, 0x00, 0xcf, 0x4a, + 0xe0, 0x7a, 0x47, 0x56, 0xc3, 0x10, 0x80, 0x2c, 0x00, 0xf4, 0x75, 0x2f, 0xb0, 0x84, 0xa2, 0x3a, + 0xcd, 0x95, 0xa6, 0x99, 0x93, 0xe3, 0x16, 0x6c, 0x85, 0xa5, 0x18, 0xe3, 0x60, 0xfc, 0xac, 0xee, + 0xba, 0xd3, 0x1f, 0x04, 0x62, 0x61, 0x6d, 0x08, 0xfe, 0x4e, 0x58, 0x8a, 0x31, 0x0e, 0xf2, 0x9b, + 0x05, 0xf8, 0x4c, 0xf4, 0x77, 0xf8, 0x23, 0xbb, 0x30, 0xf1, 0x8f, 0xac, 0x75, 0x72, 0xdc, 0xfa, + 0x4c, 0x67, 0xb4, 0x48, 0x7c, 0x5c, 0x7b, 0xc8, 0x87, 0x05, 0x98, 0x19, 0xf4, 0x4d, 0x3d, 0xa0, + 0x9d, 0x80, 0xed, 0x78, 0xba, 0x47, 0x73, 0xb3, 0xbc, 0x89, 0xb7, 0xc6, 0x9f, 0x05, 0x13, 0x70, + 0xd1, 0x6b, 0x4e, 0x96, 0x63, 0x4a, 0xac, 0xf6, 0x36, 0x4c, 0x2f, 0x0f, 0x82, 0x7d, 0xd7, 0xb3, + 0x3e, 0xe0, 0xea, 0x3f, 0x59, 0x83, 0x4a, 0xc0, 0xd5, 0x38, 0xa1, 0x21, 0x7c, 0x3e, 0xeb, 0xa5, + 0x0b, 0x95, 0xfa, 0x0e, 0x3d, 0x52, 0x7a, 0x89, 0x58, 0xa9, 0x85, 0x5a, 0x27, 0xaa, 0x6b, 0x7f, + 0xb2, 0x00, 0xb5, 0xb6, 0x6e, 0x1c, 0xb8, 0x7b, 0x7b, 0xe4, 0x1d, 0xa8, 0x5b, 0x4e, 0x40, 0xbd, + 0x43, 0xdd, 0x96, 0xb0, 0x0b, 0x31, 0xd8, 0x70, 0x43, 0x18, 0x3d, 0x1e, 0xdb, 0x7d, 0x31, 0x41, + 0xab, 0x03, 0xb9, 0x6b, 0xe1, 0x9a, 0xf1, 0xba, 0xc4, 0xc0, 0x10, 0x8d, 0xb4, 0xa0, 0xe2, 0x07, + 0xb4, 0xef, 0xf3, 0x35, 0x70, 0x5a, 0x34, 0xa3, 0xc3, 0x0a, 0x50, 0x94, 0x6b, 0x7f, 0xa5, 0x00, + 0x8d, 0xb6, 0xee, 0x5b, 0x06, 0x7b, 0x4a, 0xb2, 0x02, 0xe5, 0x81, 0x4f, 0xbd, 0xb3, 0x3d, 0x1b, + 0x5f, 0xb6, 0x76, 0x7c, 0xea, 0x21, 0xaf, 0x4c, 0xee, 0x41, 0xbd, 0xaf, 0xfb, 0xfe, 0x03, 0xd7, + 0x33, 0xe5, 0xd2, 0x7b, 0x4a, 0x20, 0xb1, 0x4d, 0x90, 0x55, 0x31, 0x04, 0xd1, 0x9a, 0x10, 0xe9, + 0x1e, 0xda, 0xef, 0x16, 0xe0, 0x62, 0x7b, 0xb0, 0xb7, 0x47, 0x3d, 0xa9, 0x15, 0x4b, 0x7d, 0x93, + 0x42, 0xc5, 0xa3, 0xa6, 0xe5, 0xcb, 0xb6, 0xaf, 0x8e, 0x3d, 0x50, 0x90, 0xa1, 0x48, 0xf5, 0x96, + 0xf7, 0x17, 0x2f, 0x40, 0x81, 0x4e, 0x06, 0xd0, 0x78, 0x9f, 0xb2, 0xdd, 0x38, 0xd5, 0x7b, 0xf2, + 0xe9, 0x6e, 0x8f, 0x2d, 0xea, 0x2d, 0x1a, 0x74, 0x38, 0x52, 0x5c, 0x9b, 0x0e, 0x0b, 0x31, 0x92, + 0xa4, 0xfd, 0x76, 0x05, 0xa6, 0x56, 0xdc, 0xde, 0xae, 0xe5, 0x50, 0xf3, 0xa6, 0xd9, 0xa5, 0xe4, + 0x3d, 0x28, 0x53, 0xb3, 0x4b, 0xe5, 0xd3, 0x8e, 0xaf, 0x78, 0x30, 0xb0, 0x48, 0x7d, 0x62, 0xff, + 0x90, 0x03, 0x93, 0x0d, 0x98, 0xd9, 0xf3, 0xdc, 0x9e, 0x98, 0xcb, 0xb7, 0x8f, 0xfa, 0x52, 0x77, + 0x6e, 0xff, 0x98, 0xfa, 0x70, 0xd6, 0x12, 0xd4, 0x47, 0xc7, 0x2d, 0x88, 0xfe, 0x61, 0xaa, 0x2e, + 0x79, 0x07, 0xe6, 0xa2, 0x92, 0x70, 0x52, 0x5b, 0x61, 0xdb, 0x19, 0xae, 0x3b, 0x55, 0xda, 0x57, + 0x4f, 0x8e, 0x5b, 0x73, 0x6b, 0x23, 0x78, 0x70, 0x64, 0x6d, 0x36, 0x55, 0xcc, 0x46, 0x44, 0xb1, + 0xd0, 0x48, 0x95, 0x69, 0x42, 0x2b, 0x18, 0xdf, 0xf7, 0xad, 0xa5, 0x44, 0xe0, 0x90, 0x50, 0xb2, + 0x06, 0x53, 0x81, 0x1b, 0xeb, 0xaf, 0x0a, 0xef, 0x2f, 0x4d, 0x19, 0x2a, 0xb6, 0xdd, 0x91, 0xbd, + 0x95, 0xa8, 0x47, 0x10, 0x2e, 0xab, 0xff, 0xa9, 0x9e, 0xaa, 0xf2, 0x9e, 0x9a, 0x3f, 0x39, 0x6e, + 0x5d, 0xde, 0xce, 0xe4, 0xc0, 0x11, 0x35, 0xc9, 0x2f, 0x17, 0x60, 0x46, 0x91, 0x64, 0x1f, 0xd5, + 0x26, 0xd9, 0x47, 0x84, 0x8d, 0x88, 0xed, 0x84, 0x00, 0x4c, 0x09, 0xd4, 0xbe, 0x5f, 0x83, 0x46, + 0x38, 0xd5, 0x93, 0xcf, 0x41, 0x85, 0x9b, 0x20, 0xa4, 0x06, 0x1f, 0xae, 0xe1, 0xdc, 0x52, 0x81, + 0x82, 0x46, 0x3e, 0x0f, 0x35, 0xc3, 0xed, 0xf5, 0x74, 0xc7, 0xe4, 0x66, 0xa5, 0x46, 0xbb, 0xc9, + 0x54, 0x97, 0x15, 0x51, 0x84, 0x8a, 0x46, 0xae, 0x42, 0x59, 0xf7, 0xba, 0xc2, 0xc2, 0xd3, 0x10, + 0xf3, 0xd1, 0xb2, 0xd7, 0xf5, 0x91, 0x97, 0x92, 0xaf, 0x40, 0x89, 0x3a, 0x87, 0x73, 0xe5, 0xd1, + 0xba, 0xd1, 0x4d, 0xe7, 0xf0, 0xbe, 0xee, 0xb5, 0x9b, 0xb2, 0x0d, 0xa5, 0x9b, 0xce, 0x21, 0xb2, + 0x3a, 0x64, 0x03, 0x6a, 0xd4, 0x39, 0x64, 0xef, 0x5e, 0x9a, 0x5e, 0x3e, 0x3b, 0xa2, 0x3a, 0x63, + 0x91, 0xdb, 0x84, 0x50, 0xc3, 0x92, 0xc5, 0xa8, 0x20, 0xc8, 0x37, 0x60, 0x4a, 0x28, 0x5b, 0x9b, + 0xec, 0x9d, 0xf8, 0x73, 0x55, 0x0e, 0xd9, 0x1a, 0xad, 0xad, 0x71, 0xbe, 0xc8, 0xd4, 0x15, 0x2b, + 0xf4, 0x31, 0x01, 0x45, 0xbe, 0x01, 0x0d, 0xb5, 0x33, 0x56, 0x6f, 0x36, 0xd3, 0x4a, 0xa4, 0xb6, + 0xd3, 0x48, 0xbf, 0x35, 0xb0, 0x3c, 0xda, 0xa3, 0x4e, 0xe0, 0xb7, 0x9f, 0x57, 0x76, 0x03, 0x45, + 0xf5, 0x31, 0x42, 0x23, 0xbb, 0xc3, 0xe6, 0x2e, 0x61, 0xab, 0xf9, 0xdc, 0x88, 0x59, 0x7d, 0x0c, + 0x5b, 0xd7, 0x37, 0xe1, 0x42, 0x68, 0x8f, 0x92, 0x26, 0x0d, 0x61, 0xbd, 0xf9, 0x12, 0xab, 0xbe, + 0x9e, 0x24, 0x3d, 0x3a, 0x6e, 0xbd, 0x94, 0x61, 0xd4, 0x88, 0x18, 0x30, 0x0d, 0x46, 0x3e, 0x80, + 0x19, 0x8f, 0xea, 0xa6, 0xe5, 0x50, 0xdf, 0xdf, 0xf2, 0xdc, 0xdd, 0xfc, 0x9a, 0x27, 0x47, 0x11, + 0xc3, 0x1e, 0x13, 0xc8, 0x98, 0x92, 0x44, 0x1e, 0xc0, 0xb4, 0x6d, 0x1d, 0xd2, 0x48, 0x74, 0x73, + 0x22, 0xa2, 0x9f, 0x3f, 0x39, 0x6e, 0x4d, 0x6f, 0xc4, 0x81, 0x31, 0x29, 0x87, 0x69, 0x2a, 0x7d, + 0xd7, 0x0b, 0x94, 0x7a, 0xfa, 0xd9, 0xc7, 0xaa, 0xa7, 0x5b, 0xae, 0x17, 0x44, 0x1f, 0x21, 0xfb, + 0xe7, 0xa3, 0xa8, 0xae, 0xfd, 0x8d, 0x0a, 0x0c, 0x6f, 0xe2, 0x92, 0x23, 0xae, 0x30, 0xe9, 0x11, + 0x97, 0x1e, 0x0d, 0x62, 0xed, 0x79, 0x5d, 0x56, 0x9b, 0xc0, 0x88, 0xc8, 0x18, 0xd5, 0xa5, 0x49, + 0x8f, 0xea, 0x67, 0x66, 0xe2, 0x19, 0x1e, 0xfe, 0xd5, 0x8f, 0x6f, 0xf8, 0xd7, 0x9e, 0xce, 0xf0, + 0xd7, 0xbe, 0x57, 0x86, 0x99, 0x55, 0x9d, 0xf6, 0x5c, 0xe7, 0x89, 0xfb, 0xf8, 0xc2, 0x33, 0xb1, + 0x8f, 0xbf, 0x01, 0x75, 0x8f, 0xf6, 0x6d, 0xcb, 0xd0, 0x85, 0xba, 0x2e, 0xed, 0xe6, 0x28, 0xcb, + 0x30, 0xa4, 0x8e, 0xb0, 0xdf, 0x94, 0x9e, 0x49, 0xfb, 0x4d, 0xf9, 0xe3, 0xb7, 0xdf, 0x68, 0xbf, + 0x5c, 0x04, 0xae, 0xda, 0x92, 0xeb, 0x50, 0x66, 0x6a, 0x5b, 0xda, 0x6a, 0xc8, 0xbf, 0x16, 0x4e, + 0x21, 0xf3, 0x50, 0x0c, 0x5c, 0x39, 0xdd, 0x80, 0xa4, 0x17, 0xb7, 0x5d, 0x2c, 0x06, 0x2e, 0xf9, + 0x00, 0xc0, 0x70, 0x1d, 0xd3, 0x52, 0xee, 0xa4, 0x7c, 0x0f, 0xb6, 0xe6, 0x7a, 0x0f, 0x74, 0xcf, + 0x5c, 0x09, 0x11, 0xc5, 0x0e, 0x3e, 0xfa, 0x8f, 0x31, 0x69, 0xe4, 0x0d, 0xa8, 0xba, 0xce, 0xda, + 0xc0, 0xb6, 0x79, 0x87, 0x36, 0xda, 0x5f, 0x38, 0x39, 0x6e, 0x55, 0xef, 0xf1, 0x92, 0x47, 0xc7, + 0xad, 0x2b, 0x62, 0x47, 0xc4, 0xfe, 0xbd, 0xed, 0x59, 0x81, 0xe5, 0x74, 0xc3, 0x0d, 0xad, 0xac, + 0xa6, 0xfd, 0x4a, 0x01, 0x9a, 0x6b, 0xd6, 0x43, 0x6a, 0xbe, 0x6d, 0x39, 0xa6, 0xfb, 0x80, 0x20, + 0x54, 0x6d, 0xea, 0x74, 0x83, 0xfd, 0x31, 0x77, 0x9c, 0xc2, 0xae, 0xc3, 0x11, 0x50, 0x22, 0x91, + 0x45, 0x68, 0x88, 0xfd, 0x8a, 0xe5, 0x74, 0x79, 0x1f, 0xd6, 0xa3, 0x99, 0xbe, 0xa3, 0x08, 0x18, + 0xf1, 0x68, 0x47, 0xf0, 0xfc, 0x50, 0x37, 0x10, 0x13, 0xca, 0x81, 0xde, 0x55, 0x8b, 0xca, 0xda, + 0xd8, 0x1d, 0xbc, 0xad, 0x77, 0x63, 0x9d, 0xcb, 0xb5, 0xc2, 0x6d, 0x9d, 0x69, 0x85, 0x0c, 0x5d, + 0xfb, 0x3f, 0x05, 0xa8, 0xaf, 0x0d, 0x1c, 0x83, 0x6f, 0xea, 0x9f, 0x6c, 0x4d, 0x56, 0x2a, 0x66, + 0x31, 0x53, 0xc5, 0x1c, 0x40, 0xf5, 0xe0, 0x41, 0xa8, 0x82, 0x36, 0x97, 0x36, 0xc7, 0x1f, 0x15, + 0xb2, 0x49, 0x0b, 0x77, 0x38, 0x9e, 0x70, 0x76, 0xce, 0xc8, 0x06, 0x55, 0xef, 0xbc, 0xcd, 0x85, + 0x4a, 0x61, 0xf3, 0x5f, 0x81, 0x66, 0x8c, 0xed, 0x4c, 0x7e, 0x8f, 0xbf, 0x59, 0x86, 0xea, 0xad, + 0x4e, 0x67, 0x79, 0x6b, 0x9d, 0xbc, 0x0a, 0x4d, 0xe9, 0x07, 0xbb, 0x1b, 0xf5, 0x41, 0xe8, 0x06, + 0xed, 0x44, 0x24, 0x8c, 0xf3, 0x31, 0x05, 0xde, 0xa3, 0xba, 0xdd, 0x93, 0x1f, 0x4b, 0xa8, 0x3b, + 0x20, 0x2b, 0x44, 0x41, 0x23, 0x3a, 0xcc, 0x0c, 0x7c, 0xea, 0xb1, 0x2e, 0x14, 0xfb, 0x7d, 0xf9, + 0xd9, 0x9c, 0xd2, 0x22, 0xc0, 0x17, 0x98, 0x9d, 0x04, 0x00, 0xa6, 0x00, 0xc9, 0xeb, 0x50, 0xd7, + 0x07, 0xc1, 0x3e, 0xdf, 0x72, 0x89, 0x6f, 0xe3, 0x2a, 0x77, 0x13, 0xca, 0xb2, 0x47, 0xc7, 0xad, + 0xa9, 0x3b, 0xd8, 0x7e, 0x55, 0xfd, 0xc7, 0x90, 0x9b, 0x35, 0x4e, 0xd9, 0x18, 0x64, 0xe3, 0x2a, + 0x67, 0x6e, 0xdc, 0x56, 0x02, 0x00, 0x53, 0x80, 0xe4, 0x5d, 0x98, 0x3a, 0xa0, 0x47, 0x81, 0xbe, + 0x2b, 0x05, 0x54, 0xcf, 0x22, 0x60, 0x96, 0x29, 0xfd, 0x77, 0x62, 0xd5, 0x31, 0x01, 0x46, 0x7c, + 0xb8, 0x74, 0x40, 0xbd, 0x5d, 0xea, 0xb9, 0xd2, 0x5e, 0x21, 0x85, 0xd4, 0xce, 0x22, 0x64, 0xee, + 0xe4, 0xb8, 0x75, 0xe9, 0x4e, 0x06, 0x0c, 0x66, 0x82, 0x6b, 0xff, 0xbb, 0x08, 0x17, 0x6e, 0x89, + 0x40, 0x04, 0xd7, 0x13, 0x9a, 0x07, 0xb9, 0x02, 0x25, 0xaf, 0x3f, 0xe0, 0x23, 0xa7, 0x24, 0x5c, + 0x0d, 0xb8, 0xb5, 0x83, 0xac, 0x8c, 0xbc, 0x03, 0x75, 0x53, 0x4e, 0x19, 0xd2, 0x5c, 0x32, 0x96, + 0x69, 0x4b, 0xfd, 0xc3, 0x10, 0x8d, 0xed, 0x0d, 0x7b, 0x7e, 0xb7, 0x63, 0x7d, 0x40, 0xa5, 0x05, + 0x81, 0xef, 0x0d, 0x37, 0x45, 0x11, 0x2a, 0x1a, 0x5b, 0x55, 0x0f, 0xe8, 0x91, 0xd8, 0x3f, 0x97, + 0xa3, 0x55, 0xf5, 0x8e, 0x2c, 0xc3, 0x90, 0x4a, 0x5a, 0xea, 0x63, 0x61, 0xa3, 0xa0, 0x2c, 0x6c, + 0x3f, 0xf7, 0x59, 0x81, 0xfc, 0x6e, 0xd8, 0x94, 0xf9, 0xbe, 0x15, 0x04, 0xd4, 0x93, 0xaf, 0x71, + 0xac, 0x29, 0xf3, 0x2d, 0x8e, 0x80, 0x12, 0x89, 0xfc, 0x04, 0x34, 0x38, 0x78, 0xdb, 0x76, 0x77, + 0xf9, 0x8b, 0x6b, 0x08, 0x2b, 0xd0, 0x7d, 0x55, 0x88, 0x11, 0x5d, 0xfb, 0x83, 0x22, 0x5c, 0xbe, + 0x45, 0x03, 0xa1, 0xd5, 0xac, 0xd2, 0xbe, 0xed, 0x1e, 0x31, 0x7d, 0x1a, 0xe9, 0xb7, 0xc8, 0x9b, + 0x00, 0x96, 0xbf, 0xdb, 0x39, 0x34, 0xf8, 0x77, 0x20, 0xbe, 0xe1, 0xeb, 0xf2, 0x93, 0x84, 0xf5, + 0x4e, 0x5b, 0x52, 0x1e, 0x25, 0xfe, 0x61, 0xac, 0x4e, 0xb4, 0x21, 0x2f, 0x3e, 0x66, 0x43, 0xde, + 0x01, 0xe8, 0x47, 0x5a, 0x79, 0x89, 0x73, 0xfe, 0x94, 0x12, 0x73, 0x16, 0x85, 0x3c, 0x06, 0x93, + 0x47, 0x4f, 0x76, 0x60, 0xd6, 0xa4, 0x7b, 0xfa, 0xc0, 0x0e, 0xc2, 0x9d, 0x84, 0xfc, 0x88, 0x4f, + 0xbf, 0x19, 0x09, 0x83, 0x24, 0x56, 0x53, 0x48, 0x38, 0x84, 0xad, 0xfd, 0xad, 0x12, 0xcc, 0xdf, + 0xa2, 0x41, 0x68, 0xa3, 0x93, 0xb3, 0x63, 0xa7, 0x4f, 0x0d, 0xf6, 0x16, 0x3e, 0x2c, 0x40, 0xd5, + 0xd6, 0x77, 0xa9, 0xcd, 0x56, 0x2f, 0xf6, 0x34, 0xef, 0x8d, 0xbd, 0x10, 0x8c, 0x96, 0xb2, 0xb0, + 0xc1, 0x25, 0xa4, 0x96, 0x06, 0x51, 0x88, 0x52, 0x3c, 0x9b, 0xd4, 0x0d, 0x7b, 0xe0, 0x07, 0x62, + 0x67, 0x27, 0xf5, 0xc9, 0x70, 0x52, 0x5f, 0x89, 0x48, 0x18, 0xe7, 0x23, 0x4b, 0x00, 0x86, 0x6d, + 0x51, 0x27, 0xe0, 0xb5, 0xc4, 0x77, 0x45, 0xd4, 0xfb, 0x5d, 0x09, 0x29, 0x18, 0xe3, 0x62, 0xa2, + 0x7a, 0xae, 0x63, 0x05, 0xae, 0x10, 0x55, 0x4e, 0x8a, 0xda, 0x8c, 0x48, 0x18, 0xe7, 0xe3, 0xd5, + 0x68, 0xe0, 0x59, 0x86, 0xcf, 0xab, 0x55, 0x52, 0xd5, 0x22, 0x12, 0xc6, 0xf9, 0xd8, 0x9a, 0x17, + 0x7b, 0xfe, 0x33, 0xad, 0x79, 0xbf, 0xd1, 0x80, 0x6b, 0x89, 0x6e, 0x0d, 0xf4, 0x80, 0xee, 0x0d, + 0xec, 0x0e, 0x0d, 0xd4, 0x0b, 0x1c, 0x73, 0x2d, 0xfc, 0x33, 0xd1, 0x7b, 0x17, 0xe1, 0x4f, 0xc6, + 0x64, 0xde, 0xfb, 0x50, 0x03, 0x4f, 0xf5, 0xee, 0x17, 0xa1, 0xe1, 0xe8, 0x81, 0xcf, 0x3f, 0x5c, + 0xf9, 0x8d, 0x86, 0x6a, 0xd8, 0x5d, 0x45, 0xc0, 0x88, 0x87, 0x6c, 0xc1, 0x25, 0xd9, 0xc5, 0x37, + 0x1f, 0xb2, 0x3d, 0x3f, 0xf5, 0x44, 0x5d, 0xb9, 0x9c, 0xca, 0xba, 0x97, 0x36, 0x33, 0x78, 0x30, + 0xb3, 0x26, 0xd9, 0x84, 0x8b, 0x86, 0x08, 0x09, 0xa1, 0xb6, 0xab, 0x9b, 0x0a, 0x50, 0x98, 0x44, + 0xc3, 0xad, 0xd1, 0xca, 0x30, 0x0b, 0x66, 0xd5, 0x4b, 0x8f, 0xe6, 0xea, 0x58, 0xa3, 0xb9, 0x36, + 0xce, 0x68, 0xae, 0x8f, 0x37, 0x9a, 0x1b, 0xa7, 0x1b, 0xcd, 0xac, 0xe7, 0xd9, 0x38, 0xa2, 0x1e, + 0x53, 0x4f, 0xc4, 0x0a, 0x1b, 0x8b, 0x38, 0x0a, 0x7b, 0xbe, 0x93, 0xc1, 0x83, 0x99, 0x35, 0xc9, + 0x2e, 0xcc, 0x8b, 0xf2, 0x9b, 0x8e, 0xe1, 0x1d, 0xf5, 0xd9, 0xc2, 0x13, 0xc3, 0x6d, 0x26, 0x6c, + 0xd2, 0xf3, 0x9d, 0x91, 0x9c, 0xf8, 0x18, 0x14, 0xf2, 0x33, 0x30, 0x2d, 0xde, 0xd2, 0xa6, 0xde, + 0xe7, 0xb0, 0x22, 0xfe, 0xe8, 0x05, 0x09, 0x3b, 0xbd, 0x12, 0x27, 0x62, 0x92, 0x97, 0x2c, 0xc3, + 0x85, 0xfe, 0xa1, 0xc1, 0x7e, 0xae, 0xef, 0xdd, 0xa5, 0xd4, 0xa4, 0x26, 0x77, 0x78, 0x36, 0xda, + 0x2f, 0x2a, 0xeb, 0xce, 0x56, 0x92, 0x8c, 0x69, 0x7e, 0xf2, 0x3a, 0x4c, 0xf9, 0x81, 0xee, 0x05, + 0xd2, 0x10, 0x3c, 0x37, 0x23, 0xe2, 0xb3, 0x94, 0x9d, 0xb4, 0x13, 0xa3, 0x61, 0x82, 0x33, 0x73, + 0xbd, 0xb8, 0x70, 0x7e, 0xeb, 0x45, 0x9e, 0xd9, 0xea, 0x1f, 0x15, 0xe1, 0xfa, 0x2d, 0x1a, 0x6c, + 0xba, 0x8e, 0x34, 0xa3, 0x67, 0x2d, 0xfb, 0xa7, 0xb2, 0xa2, 0x27, 0x17, 0xed, 0xe2, 0x44, 0x17, + 0xed, 0xd2, 0x84, 0x16, 0xed, 0xf2, 0x39, 0x2e, 0xda, 0x7f, 0xa7, 0x08, 0x2f, 0x26, 0x7a, 0x72, + 0xcb, 0x35, 0xd5, 0x84, 0xff, 0x69, 0x07, 0x9e, 0xa2, 0x03, 0x1f, 0x09, 0xbd, 0x93, 0x3b, 0x42, + 0x53, 0x1a, 0xcf, 0x77, 0xd3, 0x1a, 0xcf, 0xbb, 0x79, 0x56, 0xbe, 0x0c, 0x09, 0xa7, 0x5a, 0xf1, + 0xde, 0x02, 0xe2, 0x49, 0xb7, 0x6d, 0x64, 0xce, 0x96, 0x4a, 0x4f, 0x18, 0x00, 0x8a, 0x43, 0x1c, + 0x98, 0x51, 0x8b, 0x74, 0xe0, 0x05, 0x9f, 0x3a, 0x81, 0xe5, 0x50, 0x3b, 0x09, 0x27, 0xb4, 0xa1, + 0x97, 0x24, 0xdc, 0x0b, 0x9d, 0x2c, 0x26, 0xcc, 0xae, 0x9b, 0x67, 0x1e, 0xf8, 0x67, 0xc0, 0x55, + 0x4e, 0xd1, 0x35, 0x13, 0xd3, 0x58, 0x3e, 0x4c, 0x6b, 0x2c, 0xef, 0xe5, 0x7f, 0x6f, 0xe3, 0x69, + 0x2b, 0x4b, 0x00, 0xfc, 0x2d, 0xc4, 0xd5, 0x95, 0x70, 0x91, 0xc6, 0x90, 0x82, 0x31, 0x2e, 0xb6, + 0x00, 0xa9, 0x7e, 0x8e, 0x6b, 0x2a, 0xe1, 0x02, 0xd4, 0x89, 0x13, 0x31, 0xc9, 0x3b, 0x52, 0xdb, + 0xa9, 0x8c, 0xad, 0xed, 0xbc, 0x05, 0x24, 0x61, 0x78, 0x14, 0x78, 0xd5, 0x64, 0xfc, 0xf1, 0xfa, + 0x10, 0x07, 0x66, 0xd4, 0x1a, 0x31, 0x94, 0x6b, 0x93, 0x1d, 0xca, 0xf5, 0xf1, 0x87, 0x32, 0x79, + 0x0f, 0xae, 0x70, 0x51, 0xb2, 0x7f, 0x92, 0xc0, 0x42, 0xef, 0xf9, 0xac, 0x04, 0xbe, 0x82, 0xa3, + 0x18, 0x71, 0x34, 0x06, 0x7b, 0x3f, 0x86, 0x47, 0x4d, 0x26, 0x5c, 0xb7, 0x47, 0xeb, 0x44, 0x2b, + 0x19, 0x3c, 0x98, 0x59, 0x93, 0x0d, 0xb1, 0x80, 0x0d, 0x43, 0x7d, 0xd7, 0xa6, 0xa6, 0x8c, 0xbf, + 0x0e, 0x87, 0xd8, 0xf6, 0x46, 0x47, 0x52, 0x30, 0xc6, 0x95, 0xa5, 0xa6, 0x4c, 0x9d, 0x51, 0x4d, + 0xb9, 0xc5, 0xad, 0xf4, 0x7b, 0x09, 0x6d, 0x48, 0xea, 0x3a, 0x61, 0x44, 0xfd, 0x4a, 0x9a, 0x01, + 0x87, 0xeb, 0x70, 0x2d, 0xd1, 0xf0, 0xac, 0x7e, 0xe0, 0x27, 0xb1, 0x66, 0x52, 0x5a, 0x62, 0x06, + 0x0f, 0x66, 0xd6, 0x64, 0xfa, 0xf9, 0x3e, 0xd5, 0xed, 0x60, 0x3f, 0x09, 0x78, 0x21, 0xa9, 0x9f, + 0xdf, 0x1e, 0x66, 0xc1, 0xac, 0x7a, 0x99, 0x0b, 0xd2, 0xec, 0xb3, 0xa9, 0x56, 0x7d, 0xa7, 0x04, + 0x57, 0x6e, 0xd1, 0x20, 0x0c, 0x4d, 0xfb, 0xd4, 0x8c, 0xf2, 0x31, 0x98, 0x51, 0x7e, 0xbd, 0x02, + 0x17, 0x6f, 0xd1, 0x60, 0x48, 0x1b, 0xfb, 0xff, 0xb4, 0xfb, 0x37, 0xe1, 0x62, 0x14, 0x0d, 0xd9, + 0x09, 0x5c, 0x4f, 0xac, 0xe5, 0xa9, 0xdd, 0x72, 0x67, 0x98, 0x05, 0xb3, 0xea, 0x91, 0x6f, 0xc0, + 0x8b, 0x7c, 0xa9, 0x77, 0xba, 0xc2, 0x3e, 0x2b, 0x8c, 0x09, 0xb1, 0xf3, 0x3c, 0x2d, 0x09, 0xf9, + 0x62, 0x27, 0x9b, 0x0d, 0x47, 0xd5, 0x27, 0xdf, 0x86, 0xa9, 0xbe, 0xd5, 0xa7, 0xb6, 0xe5, 0x70, + 0xfd, 0x2c, 0x77, 0x10, 0xd1, 0x56, 0x0c, 0x2c, 0xda, 0xc0, 0xc5, 0x4b, 0x31, 0x21, 0x30, 0x73, + 0xa4, 0xd6, 0xcf, 0x71, 0xa4, 0xfe, 0x8f, 0x22, 0xd4, 0x6e, 0x79, 0xee, 0xa0, 0xdf, 0x3e, 0x22, + 0x5d, 0xa8, 0x3e, 0xe0, 0xce, 0x33, 0xe9, 0x9a, 0x1a, 0xff, 0x44, 0x81, 0xf0, 0xc1, 0x45, 0x2a, + 0x91, 0xf8, 0x8f, 0x12, 0x9e, 0x0d, 0xe2, 0x03, 0x7a, 0x44, 0x4d, 0xe9, 0x43, 0x0b, 0x07, 0xf1, + 0x1d, 0x56, 0x88, 0x82, 0x46, 0x7a, 0x70, 0x41, 0xb7, 0x6d, 0xf7, 0x01, 0x35, 0x37, 0xf4, 0x80, + 0xfb, 0xbd, 0xa5, 0x6f, 0xe5, 0xac, 0x66, 0x69, 0x1e, 0xcc, 0xb0, 0x9c, 0x84, 0xc2, 0x34, 0x36, + 0x79, 0x1f, 0x6a, 0x7e, 0xe0, 0x7a, 0x4a, 0xd9, 0x6a, 0x2e, 0xad, 0x8c, 0xff, 0xd2, 0xdb, 0x5f, + 0xef, 0x08, 0x28, 0x61, 0xb3, 0x97, 0x7f, 0x50, 0x09, 0xd0, 0x7e, 0xad, 0x00, 0x70, 0x7b, 0x7b, + 0x7b, 0x4b, 0xba, 0x17, 0x4c, 0x28, 0xeb, 0x83, 0xd0, 0x51, 0x39, 0xbe, 0x43, 0x30, 0x11, 0xc8, + 0x2b, 0x7d, 0x78, 0x83, 0x60, 0x1f, 0x39, 0x3a, 0xf9, 0x71, 0xa8, 0x49, 0x05, 0x59, 0x76, 0x7b, + 0x18, 0x4f, 0x21, 0x95, 0x68, 0x54, 0x74, 0xed, 0xb7, 0x8a, 0x00, 0xeb, 0xa6, 0x4d, 0x3b, 0xea, + 0x10, 0x48, 0x23, 0xd8, 0xf7, 0xa8, 0xbf, 0xef, 0xda, 0xe6, 0x98, 0xde, 0x54, 0x6e, 0xf3, 0xdf, + 0x56, 0x20, 0x18, 0xe1, 0x11, 0x13, 0xa6, 0xfc, 0x80, 0xf6, 0x55, 0x6c, 0xef, 0x98, 0x4e, 0x94, + 0x59, 0x61, 0x17, 0x89, 0x70, 0x30, 0x81, 0x4a, 0x74, 0x68, 0x5a, 0x8e, 0x21, 0x3e, 0x90, 0xf6, + 0xd1, 0x98, 0x03, 0xe9, 0x02, 0xdb, 0x71, 0xac, 0x47, 0x30, 0x18, 0xc7, 0xd4, 0x7e, 0xa7, 0x08, + 0x97, 0xb9, 0x3c, 0xd6, 0x8c, 0x44, 0x04, 0x2f, 0xf9, 0xe3, 0x43, 0x07, 0x56, 0xff, 0xe8, 0xe9, + 0x44, 0x8b, 0xf3, 0x8e, 0x9b, 0x34, 0xd0, 0x23, 0x7d, 0x2e, 0x2a, 0x8b, 0x9d, 0x52, 0x1d, 0x40, + 0xd9, 0x67, 0xf3, 0x95, 0xe8, 0xbd, 0xce, 0xd8, 0x43, 0x28, 0xfb, 0x01, 0xf8, 0xec, 0x15, 0x7a, + 0x8d, 0xf9, 0xac, 0xc5, 0xc5, 0x91, 0x5f, 0x84, 0xaa, 0x1f, 0xe8, 0xc1, 0x40, 0x7d, 0x9a, 0x3b, + 0x93, 0x16, 0xcc, 0xc1, 0xa3, 0x79, 0x44, 0xfc, 0x47, 0x29, 0x54, 0xfb, 0x9d, 0x02, 0xcc, 0x67, + 0x57, 0xdc, 0xb0, 0xfc, 0x80, 0xfc, 0xb1, 0xa1, 0x6e, 0x3f, 0xe5, 0x1b, 0x67, 0xb5, 0x79, 0xa7, + 0x87, 0x67, 0x1a, 0x54, 0x49, 0xac, 0xcb, 0x03, 0xa8, 0x58, 0x01, 0xed, 0xa9, 0xfd, 0xe5, 0xbd, + 0x09, 0x3f, 0x7a, 0x6c, 0x69, 0x67, 0x52, 0x50, 0x08, 0xd3, 0xbe, 0x57, 0x1c, 0xf5, 0xc8, 0x7c, + 0xf9, 0xb0, 0x93, 0x51, 0xe2, 0x77, 0xf2, 0x45, 0x89, 0x27, 0x1b, 0x34, 0x1c, 0x2c, 0xfe, 0x27, + 0x86, 0x83, 0xc5, 0xef, 0xe5, 0x0f, 0x16, 0x4f, 0x75, 0xc3, 0xc8, 0x98, 0xf1, 0x8f, 0x4a, 0x70, + 0xf5, 0x71, 0xc3, 0x86, 0xad, 0x67, 0x72, 0x74, 0xe6, 0x5d, 0xcf, 0x1e, 0x3f, 0x0e, 0xc9, 0x12, + 0x54, 0xfa, 0xfb, 0xba, 0xaf, 0x94, 0xb2, 0xab, 0x61, 0x98, 0x21, 0x2b, 0x7c, 0xc4, 0x26, 0x0d, + 0xae, 0xcc, 0xf1, 0xbf, 0x28, 0x58, 0xd9, 0x74, 0xdc, 0xa3, 0xbe, 0x1f, 0xd9, 0x04, 0xc2, 0xe9, + 0x78, 0x53, 0x14, 0xa3, 0xa2, 0x93, 0x00, 0xaa, 0xc2, 0xc4, 0x2c, 0x57, 0xa6, 0xf1, 0x03, 0xb9, + 0x32, 0x0e, 0x16, 0x44, 0x0f, 0x25, 0xbd, 0x15, 0x52, 0x16, 0x59, 0x80, 0x72, 0x10, 0x85, 0x79, + 0xab, 0xad, 0x79, 0x39, 0x43, 0x3f, 0xe5, 0x7c, 0x6c, 0x63, 0xef, 0xee, 0x72, 0xa3, 0xba, 0x29, + 0xfd, 0xe7, 0x96, 0xeb, 0x70, 0x85, 0xac, 0x14, 0x6d, 0xec, 0xef, 0x0d, 0x71, 0x60, 0x46, 0x2d, + 0xed, 0x5f, 0xd6, 0xe1, 0x72, 0xf6, 0x78, 0x60, 0xfd, 0x76, 0x48, 0x3d, 0x9f, 0x61, 0x17, 0x92, + 0xfd, 0x76, 0x5f, 0x14, 0xa3, 0xa2, 0x7f, 0xa2, 0x03, 0xce, 0x7e, 0xbd, 0x00, 0x57, 0x3c, 0xe9, + 0x23, 0x7a, 0x1a, 0x41, 0x67, 0x2f, 0x09, 0x73, 0xc6, 0x08, 0x81, 0x38, 0xba, 0x2d, 0xe4, 0xaf, + 0x15, 0x60, 0xae, 0x97, 0xb2, 0x73, 0x9c, 0xe3, 0x99, 0x4b, 0x7e, 0x8e, 0x62, 0x73, 0x84, 0x3c, + 0x1c, 0xd9, 0x12, 0xf2, 0x6d, 0x68, 0xf6, 0xd9, 0xb8, 0xf0, 0x03, 0xea, 0x18, 0x2a, 0x40, 0x74, + 0xfc, 0x2f, 0x69, 0x2b, 0xc2, 0x0a, 0xcf, 0x5c, 0x71, 0xfd, 0x20, 0x46, 0xc0, 0xb8, 0xc4, 0x67, + 0xfc, 0x90, 0xe5, 0x0d, 0xa8, 0xfb, 0x34, 0x08, 0x2c, 0xa7, 0x2b, 0xf6, 0x1b, 0x0d, 0xf1, 0xad, + 0x74, 0x64, 0x19, 0x86, 0x54, 0xf2, 0x13, 0xd0, 0xe0, 0x2e, 0xa7, 0x65, 0xaf, 0xeb, 0xcf, 0x35, + 0x78, 0xb8, 0xd8, 0xb4, 0x08, 0x80, 0x93, 0x85, 0x18, 0xd1, 0xc9, 0x97, 0x60, 0x6a, 0x97, 0x7f, + 0xbe, 0xf2, 0xdc, 0xbd, 0xb0, 0x71, 0x71, 0x6d, 0xad, 0x1d, 0x2b, 0xc7, 0x04, 0x17, 0x59, 0x02, + 0xa0, 0xa1, 0x5f, 0x2e, 0x6d, 0xcf, 0x8a, 0x3c, 0x76, 0x18, 0xe3, 0x22, 0x2f, 0x41, 0x29, 0xb0, + 0x7d, 0x6e, 0xc3, 0xaa, 0x47, 0x5b, 0xd0, 0xed, 0x8d, 0x0e, 0xb2, 0x72, 0xed, 0x0f, 0x0a, 0x70, + 0x21, 0x75, 0x1c, 0x89, 0x55, 0x19, 0x78, 0xb6, 0x9c, 0x46, 0xc2, 0x2a, 0x3b, 0xb8, 0x81, 0xac, + 0x9c, 0xbc, 0x27, 0xd5, 0xf2, 0x62, 0xce, 0x14, 0x23, 0x77, 0xf5, 0xc0, 0x67, 0x7a, 0xf8, 0x90, + 0x46, 0xce, 0xdd, 0x7c, 0x51, 0x7b, 0xe4, 0x3a, 0x10, 0x73, 0xf3, 0x45, 0x34, 0x4c, 0x70, 0xa6, + 0x0c, 0x7e, 0xe5, 0xd3, 0x18, 0xfc, 0xb4, 0x5f, 0x29, 0xc6, 0x7a, 0x40, 0x6a, 0xf6, 0x4f, 0xe8, + 0x81, 0x97, 0xd9, 0x02, 0x1a, 0x2e, 0xee, 0x8d, 0xf8, 0xfa, 0xc7, 0x17, 0x63, 0x49, 0x25, 0x6f, + 0x8b, 0xbe, 0x2f, 0xe5, 0x3c, 0xc8, 0xbd, 0xbd, 0xd1, 0x11, 0xd1, 0x55, 0xea, 0xad, 0x85, 0xaf, + 0xa0, 0x7c, 0x4e, 0xaf, 0x40, 0xfb, 0x27, 0x25, 0x68, 0xbe, 0xe5, 0xee, 0x7e, 0x42, 0x22, 0xa8, + 0xb3, 0x97, 0xa9, 0xe2, 0xc7, 0xb8, 0x4c, 0xed, 0xc0, 0x8b, 0x41, 0x60, 0x77, 0xa8, 0xe1, 0x3a, + 0xa6, 0xbf, 0xbc, 0x17, 0x50, 0x6f, 0xcd, 0x72, 0x2c, 0x7f, 0x9f, 0x9a, 0xd2, 0x9d, 0xf4, 0x99, + 0x93, 0xe3, 0xd6, 0x8b, 0xdb, 0xdb, 0x1b, 0x59, 0x2c, 0x38, 0xaa, 0x2e, 0x9f, 0x36, 0xc4, 0xd9, + 0x51, 0x7e, 0xb6, 0x4a, 0xc6, 0xdc, 0x88, 0x69, 0x23, 0x56, 0x8e, 0x09, 0x2e, 0xed, 0xdf, 0x15, + 0xa1, 0x11, 0x26, 0x8f, 0x20, 0x9f, 0x87, 0xda, 0xae, 0xe7, 0x1e, 0x50, 0x4f, 0x78, 0xee, 0xe4, + 0xd9, 0xaa, 0xb6, 0x28, 0x42, 0x45, 0x23, 0x9f, 0x83, 0x4a, 0xe0, 0xf6, 0x2d, 0x23, 0x6d, 0x50, + 0xdb, 0x66, 0x85, 0x28, 0x68, 0xfc, 0x43, 0xe0, 0x61, 0x85, 0xfc, 0xa9, 0xea, 0xb1, 0x0f, 0x81, + 0x97, 0xa2, 0xa4, 0xaa, 0x0f, 0xa1, 0x3c, 0xf1, 0x0f, 0xe1, 0xe5, 0x50, 0x05, 0xac, 0x24, 0xbf, + 0xc4, 0x94, 0xd2, 0xf6, 0x2e, 0x94, 0x7d, 0xdd, 0xb7, 0xe5, 0xf2, 0x96, 0x23, 0x5f, 0xc3, 0x72, + 0x67, 0x43, 0xe6, 0x6b, 0x58, 0xee, 0x6c, 0x20, 0x07, 0xd5, 0x7e, 0xab, 0x04, 0x4d, 0xd1, 0xbf, + 0x62, 0xf6, 0x98, 0x64, 0x0f, 0xbf, 0xc1, 0x43, 0x2e, 0xfc, 0x41, 0x8f, 0x7a, 0xdc, 0x1c, 0x25, + 0x27, 0xc3, 0xb8, 0x1f, 0x21, 0x22, 0x86, 0x61, 0x17, 0x51, 0xd1, 0x1f, 0xee, 0xae, 0x67, 0x4b, + 0x05, 0x4f, 0x80, 0x22, 0x75, 0x5c, 0x19, 0x49, 0x19, 0x2e, 0x15, 0x77, 0x62, 0x34, 0x4c, 0x70, + 0x6a, 0xff, 0xbd, 0x08, 0x8d, 0x0d, 0x6b, 0x8f, 0x1a, 0x47, 0x86, 0x4d, 0xc9, 0x37, 0x61, 0xde, + 0xa4, 0x36, 0x65, 0x2b, 0xe6, 0x2d, 0x4f, 0x37, 0xe8, 0x16, 0xf5, 0x2c, 0x9e, 0xc0, 0x89, 0x7d, + 0x83, 0x32, 0xc0, 0xf5, 0xda, 0xc9, 0x71, 0x6b, 0x7e, 0x75, 0x24, 0x17, 0x3e, 0x06, 0x81, 0xac, + 0xc3, 0x94, 0x49, 0x7d, 0xcb, 0xa3, 0xe6, 0x56, 0x6c, 0x43, 0xf4, 0x79, 0xd5, 0xce, 0xd5, 0x18, + 0xed, 0xd1, 0x71, 0x6b, 0x5a, 0x19, 0x42, 0xc5, 0xce, 0x28, 0x51, 0x95, 0x4d, 0x2d, 0x7d, 0x7d, + 0xe0, 0xd3, 0x8c, 0x76, 0x96, 0x78, 0x3b, 0xf9, 0xd4, 0xb2, 0x95, 0xcd, 0x82, 0xa3, 0xea, 0x92, + 0x5d, 0x98, 0xe3, 0xed, 0xcf, 0xc2, 0x2d, 0x73, 0xdc, 0x97, 0x4f, 0x8e, 0x5b, 0xda, 0x2a, 0xed, + 0x7b, 0xd4, 0xd0, 0x03, 0x6a, 0xae, 0x8e, 0xe0, 0xc6, 0x91, 0x38, 0x5a, 0x05, 0x4a, 0x1b, 0x6e, + 0x57, 0xfb, 0x5e, 0x09, 0xc2, 0x8c, 0x62, 0xe4, 0x4f, 0x17, 0xa0, 0xa9, 0x3b, 0x8e, 0x1b, 0xc8, + 0x6c, 0x5d, 0x22, 0x9a, 0x00, 0x73, 0x27, 0x2e, 0x5b, 0x58, 0x8e, 0x40, 0x85, 0x23, 0x3a, 0x74, + 0x8e, 0xc7, 0x28, 0x18, 0x97, 0x4d, 0x06, 0x29, 0xdf, 0xf8, 0x66, 0xfe, 0x56, 0x9c, 0xc2, 0x13, + 0x3e, 0xff, 0x35, 0x98, 0x4d, 0x37, 0xf6, 0x2c, 0xae, 0xad, 0x5c, 0x41, 0x06, 0x45, 0x80, 0x28, + 0x3e, 0xe6, 0x29, 0x18, 0xe4, 0xac, 0x84, 0x41, 0x6e, 0xfc, 0xb4, 0x0e, 0x51, 0xa3, 0x47, 0x1a, + 0xe1, 0xbe, 0x95, 0x32, 0xc2, 0xad, 0x4f, 0x42, 0xd8, 0xe3, 0x0d, 0x6f, 0xbb, 0x70, 0x31, 0xe2, + 0x8d, 0x66, 0x97, 0x3b, 0xa9, 0xaf, 0x5f, 0xe8, 0x95, 0x5f, 0x18, 0xf1, 0xf5, 0x5f, 0x88, 0x05, + 0x2c, 0x0d, 0x7f, 0xff, 0xda, 0x5f, 0x2f, 0xc0, 0x6c, 0x5c, 0x08, 0x3f, 0x83, 0xfe, 0x65, 0x98, + 0xf6, 0xa8, 0x6e, 0xb6, 0xf5, 0xc0, 0xd8, 0xe7, 0xa1, 0xf1, 0x05, 0x1e, 0xcb, 0xce, 0x4f, 0xcb, + 0x61, 0x9c, 0x80, 0x49, 0x3e, 0xa2, 0x43, 0x93, 0x15, 0x6c, 0x5b, 0x3d, 0xea, 0x0e, 0x82, 0x31, + 0xad, 0xcc, 0x7c, 0x83, 0x87, 0x11, 0x0c, 0xc6, 0x31, 0xb5, 0x8f, 0x0a, 0x30, 0x13, 0x6f, 0xf0, + 0xb9, 0x5b, 0x20, 0xf7, 0x93, 0x16, 0xc8, 0x95, 0x09, 0xbc, 0xf7, 0x11, 0x56, 0xc7, 0xef, 0x34, + 0xe3, 0x8f, 0xc6, 0x2d, 0x8d, 0x71, 0xe3, 0x4a, 0xe1, 0xb1, 0xc6, 0x95, 0x4f, 0x7e, 0xa2, 0xaa, + 0x51, 0xbb, 0x82, 0xf2, 0x33, 0xbc, 0x2b, 0xf8, 0x38, 0xb3, 0x5d, 0xc5, 0x32, 0x36, 0x55, 0x73, + 0x64, 0x6c, 0xea, 0x85, 0x19, 0x9b, 0x6a, 0x13, 0x9b, 0xd8, 0x4e, 0x93, 0xb5, 0xa9, 0xfe, 0x54, + 0xb3, 0x36, 0x35, 0xce, 0x2b, 0x6b, 0x13, 0xe4, 0xcd, 0xda, 0xf4, 0xdd, 0x02, 0xcc, 0x98, 0x89, + 0x13, 0xc6, 0xf2, 0x6c, 0xff, 0xf8, 0xcb, 0x59, 0xf2, 0xc0, 0xb2, 0x38, 0x62, 0x96, 0x2c, 0xc3, + 0x94, 0xc8, 0xac, 0x5c, 0x49, 0x53, 0x1f, 0x4b, 0xae, 0x24, 0xf2, 0x8b, 0xd0, 0xb0, 0xd5, 0x5a, + 0x27, 0x33, 0x48, 0x6e, 0x4c, 0x64, 0x48, 0x4a, 0xcc, 0xe8, 0x14, 0x43, 0x58, 0x84, 0x91, 0x44, + 0xed, 0xf7, 0x6a, 0xf1, 0x05, 0xf1, 0x69, 0xfb, 0x38, 0x5e, 0x4b, 0xfa, 0x38, 0xae, 0xa7, 0x7d, + 0x1c, 0x43, 0xab, 0xb9, 0xf4, 0x73, 0x7c, 0x31, 0xb6, 0x4e, 0x94, 0x78, 0x92, 0xa6, 0x70, 0xc8, + 0x65, 0xac, 0x15, 0xcb, 0x70, 0x41, 0x2a, 0x01, 0x8a, 0xc8, 0x27, 0xd9, 0xe9, 0x28, 0x2a, 0x6d, + 0x35, 0x49, 0xc6, 0x34, 0x3f, 0x13, 0xe8, 0xab, 0x5c, 0xbd, 0x62, 0xc7, 0x16, 0x8d, 0x71, 0x95, + 0x47, 0x37, 0xe4, 0x60, 0xbb, 0x3b, 0x8f, 0xea, 0xbe, 0xf4, 0x54, 0xc4, 0x76, 0x77, 0xc8, 0x4b, + 0x51, 0x52, 0xe3, 0xee, 0x9a, 0xda, 0x13, 0xdc, 0x35, 0x3a, 0x34, 0x6d, 0xdd, 0x0f, 0xc4, 0x60, + 0x32, 0xe5, 0x6c, 0xf2, 0x47, 0x4e, 0xb7, 0xee, 0x33, 0x5d, 0x22, 0x52, 0xe0, 0x37, 0x22, 0x18, + 0x8c, 0x63, 0x12, 0x13, 0xa6, 0xd8, 0x5f, 0x3e, 0xb3, 0x98, 0xcb, 0x81, 0xcc, 0x68, 0x77, 0x16, + 0x19, 0xe1, 0xd6, 0x71, 0x23, 0x86, 0x83, 0x09, 0xd4, 0x11, 0x1e, 0x1d, 0x18, 0xc7, 0xa3, 0x43, + 0x7e, 0x46, 0x28, 0x6e, 0x47, 0xe1, 0x6b, 0x6d, 0xf2, 0xd7, 0x1a, 0x46, 0xb4, 0x62, 0x9c, 0x88, + 0x49, 0x5e, 0x36, 0x2a, 0x06, 0xb2, 0x1b, 0x54, 0xf5, 0xa9, 0xe4, 0xa8, 0xd8, 0x49, 0x92, 0x31, + 0xcd, 0x4f, 0xb6, 0xe0, 0x52, 0x58, 0x14, 0x6f, 0xc6, 0x34, 0xc7, 0x09, 0x43, 0x0c, 0x77, 0x32, + 0x78, 0x30, 0xb3, 0x26, 0x3f, 0xb3, 0x33, 0xf0, 0x3c, 0xea, 0x04, 0xb7, 0x75, 0x7f, 0x5f, 0xc6, + 0x2a, 0x46, 0x67, 0x76, 0x22, 0x12, 0xc6, 0xf9, 0xc8, 0x12, 0x80, 0x80, 0xe3, 0xb5, 0x2e, 0x24, + 0xc3, 0x81, 0x77, 0x42, 0x0a, 0xc6, 0xb8, 0xb4, 0xef, 0x36, 0xa0, 0x79, 0x57, 0x0f, 0xac, 0x43, + 0xca, 0xdd, 0xaf, 0xe7, 0xe3, 0x03, 0xfb, 0x4b, 0x05, 0xb8, 0x9c, 0x8c, 0xb1, 0x3d, 0x47, 0x47, + 0x18, 0xcf, 0xf1, 0x84, 0x99, 0xd2, 0x70, 0x44, 0x2b, 0xb8, 0x4b, 0x6c, 0x28, 0x64, 0xf7, 0xbc, + 0x5d, 0x62, 0x9d, 0x51, 0x02, 0x71, 0x74, 0x5b, 0x3e, 0x29, 0x2e, 0xb1, 0x67, 0x3b, 0x29, 0x69, + 0xca, 0x61, 0x57, 0x7b, 0x66, 0x1c, 0x76, 0xf5, 0x67, 0x42, 0xeb, 0xef, 0xc7, 0x1c, 0x76, 0x8d, + 0x9c, 0x81, 0x63, 0xf2, 0x58, 0x8a, 0x40, 0x1b, 0xe5, 0xf8, 0xe3, 0x19, 0x25, 0x94, 0x23, 0x85, + 0x29, 0xcb, 0xbb, 0xba, 0x6f, 0x19, 0x52, 0xed, 0xc8, 0x91, 0x84, 0x59, 0x25, 0x67, 0x14, 0xf1, + 0x25, 0xfc, 0x2f, 0x0a, 0xec, 0x28, 0x17, 0x65, 0x31, 0x57, 0x2e, 0x4a, 0xb2, 0x02, 0x65, 0xe7, + 0x80, 0x1e, 0x9d, 0x2d, 0x37, 0x03, 0xdf, 0x04, 0xde, 0xbd, 0x43, 0x8f, 0x90, 0x57, 0xd6, 0xbe, + 0x5f, 0x04, 0x60, 0x8f, 0x7f, 0x3a, 0xd7, 0xd9, 0x8f, 0x43, 0xcd, 0x1f, 0x70, 0xc3, 0x90, 0x54, + 0x98, 0xa2, 0x68, 0x3b, 0x51, 0x8c, 0x8a, 0x4e, 0x3e, 0x07, 0x95, 0x6f, 0x0d, 0xe8, 0x40, 0xc5, + 0x81, 0x84, 0xfb, 0x86, 0xaf, 0xb3, 0x42, 0x14, 0xb4, 0xf3, 0x33, 0x6f, 0x2b, 0x17, 0x5b, 0xe5, + 0xbc, 0x5c, 0x6c, 0x0d, 0xa8, 0xdd, 0x75, 0x79, 0xf0, 0xae, 0xf6, 0x5f, 0x8a, 0x00, 0x51, 0x70, + 0x24, 0xf9, 0xb5, 0x02, 0xbc, 0x10, 0x7e, 0x70, 0x81, 0xd8, 0xfe, 0xf1, 0xbc, 0xe7, 0xb9, 0xdd, + 0x6d, 0x59, 0x1f, 0x3b, 0x9f, 0x81, 0xb6, 0xb2, 0xc4, 0x61, 0x76, 0x2b, 0x08, 0x42, 0x9d, 0xf6, + 0xfa, 0xc1, 0xd1, 0xaa, 0xe5, 0xc9, 0x11, 0x98, 0x19, 0x83, 0x7b, 0x53, 0xf2, 0x88, 0xaa, 0xd2, + 0x46, 0xc1, 0x3f, 0x22, 0x45, 0xc1, 0x10, 0x87, 0xec, 0x43, 0xdd, 0x71, 0xdf, 0xf3, 0x59, 0x77, + 0xc8, 0xe1, 0xf8, 0xe6, 0xf8, 0x5d, 0x2e, 0xba, 0x55, 0xb8, 0x5d, 0xe4, 0x1f, 0xac, 0x39, 0xb2, + 0xb3, 0x7f, 0xb5, 0x08, 0x17, 0x33, 0xfa, 0x81, 0xbc, 0x09, 0xb3, 0x32, 0x0e, 0x35, 0xba, 0x00, + 0xa0, 0x10, 0x5d, 0x00, 0xd0, 0x49, 0xd1, 0x70, 0x88, 0x9b, 0xbc, 0x07, 0xa0, 0x1b, 0x06, 0xf5, + 0xfd, 0x4d, 0xd7, 0x54, 0xfb, 0x81, 0x37, 0x98, 0xfa, 0xb2, 0x1c, 0x96, 0x3e, 0x3a, 0x6e, 0xfd, + 0x64, 0x56, 0x68, 0x79, 0xaa, 0x9f, 0xa3, 0x0a, 0x18, 0x83, 0x24, 0xdf, 0x04, 0x10, 0x36, 0x80, + 0x30, 0xfb, 0xc5, 0x13, 0x0c, 0x67, 0x0b, 0x2a, 0xb9, 0xda, 0xc2, 0xd7, 0x07, 0xba, 0x13, 0x58, + 0xc1, 0x91, 0x48, 0x36, 0x74, 0x3f, 0x44, 0xc1, 0x18, 0xa2, 0xf6, 0x0f, 0x8b, 0x50, 0x57, 0xae, + 0x87, 0xa7, 0x60, 0x0b, 0xee, 0x26, 0x6c, 0xc1, 0x13, 0x0a, 0x26, 0xcf, 0xb2, 0x04, 0xbb, 0x29, + 0x4b, 0xf0, 0xad, 0xfc, 0xa2, 0x1e, 0x6f, 0x07, 0xfe, 0xcd, 0x22, 0xcc, 0x28, 0xd6, 0xbc, 0x16, + 0xda, 0xaf, 0xc2, 0x05, 0x11, 0x04, 0xb2, 0xa9, 0x3f, 0x14, 0x79, 0x97, 0x78, 0x87, 0x95, 0x45, + 0xfc, 0x76, 0x3b, 0x49, 0xc2, 0x34, 0x2f, 0x1b, 0xd6, 0xa2, 0x68, 0x87, 0x6d, 0xc2, 0x84, 0xdb, + 0x58, 0xec, 0x37, 0xf9, 0xb0, 0x6e, 0xa7, 0x68, 0x38, 0xc4, 0x9d, 0x36, 0x11, 0x97, 0xcf, 0xc1, + 0x44, 0xfc, 0xaf, 0x0b, 0x30, 0x15, 0xf5, 0xd7, 0xb9, 0x1b, 0x88, 0xf7, 0x92, 0x06, 0xe2, 0xe5, + 0xdc, 0xc3, 0x61, 0x84, 0x79, 0xf8, 0xcf, 0xd5, 0x20, 0x71, 0xa6, 0x81, 0xec, 0xc2, 0xbc, 0x95, + 0x19, 0x99, 0x19, 0x9b, 0x6d, 0xc2, 0x43, 0xfa, 0xeb, 0x23, 0x39, 0xf1, 0x31, 0x28, 0x64, 0x00, + 0xf5, 0x43, 0xea, 0x05, 0x96, 0x41, 0xd5, 0xf3, 0xdd, 0xca, 0xad, 0x92, 0x49, 0x23, 0x78, 0xd8, + 0xa7, 0xf7, 0xa5, 0x00, 0x0c, 0x45, 0x91, 0x5d, 0xa8, 0x50, 0xb3, 0x4b, 0x55, 0x26, 0xac, 0x9c, + 0x99, 0x89, 0xc3, 0xfe, 0x64, 0xff, 0x7c, 0x14, 0xd0, 0xc4, 0x8f, 0x1b, 0x9a, 0xca, 0x39, 0x15, + 0xac, 0x53, 0x9a, 0x97, 0xc8, 0x41, 0x68, 0x6d, 0xad, 0x4c, 0x68, 0xf2, 0x78, 0x8c, 0xad, 0xd5, + 0x87, 0xc6, 0x03, 0x3d, 0xa0, 0x5e, 0x4f, 0xf7, 0x0e, 0xe4, 0x6e, 0x63, 0xfc, 0x27, 0x7c, 0x5b, + 0x21, 0x45, 0x4f, 0x18, 0x16, 0x61, 0x24, 0x87, 0xb8, 0xd0, 0x08, 0xa4, 0xfa, 0xac, 0x4c, 0xca, + 0xe3, 0x0b, 0x55, 0x8a, 0xb8, 0x2f, 0xcf, 0x36, 0xa8, 0xbf, 0x18, 0xc9, 0x20, 0x87, 0x89, 0x34, + 0xf6, 0xe2, 0xf2, 0x82, 0x76, 0x0e, 0xd7, 0x84, 0x84, 0x8a, 0x96, 0x9b, 0xec, 0x74, 0xf8, 0xda, + 0xff, 0xac, 0x44, 0xd3, 0xf2, 0xd3, 0xb6, 0x13, 0x7e, 0x29, 0x69, 0x27, 0xbc, 0x96, 0xb6, 0x13, + 0xa6, 0x7c, 0xfe, 0x67, 0x8f, 0x86, 0x4e, 0x99, 0xd7, 0xca, 0xe7, 0x60, 0x5e, 0x7b, 0x05, 0x9a, + 0x87, 0x7c, 0x26, 0x10, 0x69, 0xb5, 0x2a, 0x7c, 0x19, 0xe1, 0x33, 0xfb, 0xfd, 0xa8, 0x18, 0xe3, + 0x3c, 0xac, 0x8a, 0xbc, 0xb8, 0x27, 0xcc, 0x64, 0x2d, 0xab, 0x74, 0xa2, 0x62, 0x8c, 0xf3, 0xf0, + 0x40, 0x4a, 0xcb, 0x39, 0x10, 0x15, 0x6a, 0xbc, 0x82, 0x08, 0xa4, 0x54, 0x85, 0x18, 0xd1, 0xc9, + 0x0d, 0xa8, 0x0f, 0xcc, 0x3d, 0xc1, 0x5b, 0xe7, 0xbc, 0x5c, 0xc3, 0xdc, 0x59, 0x5d, 0x93, 0x69, + 0xbe, 0x14, 0x95, 0xb5, 0xa4, 0xa7, 0xf7, 0x15, 0x81, 0xef, 0x0d, 0x65, 0x4b, 0x36, 0xa3, 0x62, + 0x8c, 0xf3, 0x90, 0x9f, 0x86, 0x19, 0x8f, 0x9a, 0x03, 0x83, 0x86, 0xb5, 0x80, 0xd7, 0x92, 0xf9, + 0x4f, 0xe3, 0x14, 0x4c, 0x71, 0x8e, 0x30, 0x12, 0x36, 0xc7, 0x32, 0x12, 0x7e, 0x0d, 0x66, 0x4c, + 0x4f, 0xb7, 0x1c, 0x6a, 0xde, 0x73, 0x78, 0x60, 0x87, 0x0c, 0xe7, 0x0c, 0x0d, 0xf4, 0xab, 0x09, + 0x2a, 0xa6, 0xb8, 0xb5, 0x7f, 0x5a, 0x84, 0x8a, 0xc8, 0xca, 0xba, 0x0e, 0x17, 0x2d, 0xc7, 0x0a, + 0x2c, 0xdd, 0x5e, 0xa5, 0xb6, 0x7e, 0x14, 0x0f, 0x70, 0xa9, 0xb4, 0x5f, 0x64, 0x1b, 0xed, 0xf5, + 0x61, 0x32, 0x66, 0xd5, 0x61, 0x9d, 0x13, 0x88, 0xe5, 0x5b, 0xa1, 0x08, 0x3b, 0x9a, 0x48, 0x09, + 0x9e, 0xa0, 0x60, 0x8a, 0x93, 0x29, 0x43, 0xfd, 0xa1, 0xc8, 0x95, 0x8a, 0x50, 0x86, 0x92, 0xc1, + 0x24, 0x49, 0x3e, 0xae, 0xa4, 0x0f, 0xb8, 0x42, 0x1c, 0x1e, 0x9a, 0x92, 0x41, 0x70, 0x42, 0x49, + 0x4f, 0xd1, 0x70, 0x88, 0x9b, 0x21, 0xec, 0xe9, 0x96, 0x3d, 0xf0, 0x68, 0x84, 0x50, 0x89, 0x10, + 0xd6, 0x52, 0x34, 0x1c, 0xe2, 0xd6, 0xb6, 0x01, 0xb6, 0x06, 0xb6, 0xaf, 0xf3, 0x0c, 0x3c, 0x13, + 0xbb, 0x17, 0xe2, 0xf7, 0x8b, 0x30, 0x25, 0x60, 0xe5, 0x46, 0x7a, 0x09, 0x40, 0x26, 0xfa, 0x31, + 0x4d, 0x4f, 0xea, 0x06, 0xd1, 0x04, 0x17, 0x52, 0x30, 0xc6, 0x75, 0xba, 0x90, 0xb2, 0xd7, 0x61, + 0x4a, 0x85, 0x88, 0x71, 0xb5, 0x23, 0x15, 0x5e, 0xbb, 0x12, 0xa3, 0x61, 0x82, 0x93, 0xac, 0xb2, + 0xde, 0xdf, 0x15, 0x07, 0xcb, 0x2d, 0xd7, 0xe1, 0xb5, 0x45, 0x06, 0x86, 0xf0, 0x68, 0x65, 0x27, + 0x45, 0xc7, 0xa1, 0x1a, 0xe4, 0x8b, 0x50, 0xef, 0xe9, 0x0f, 0x77, 0x1c, 0xdd, 0x38, 0x90, 0x53, + 0x48, 0xa8, 0x57, 0x6c, 0xca, 0x72, 0x0c, 0x39, 0x88, 0x2e, 0xf7, 0xe1, 0xd5, 0xbc, 0x87, 0x0f, + 0xc3, 0x57, 0x36, 0xb4, 0x13, 0xff, 0x6f, 0x05, 0x20, 0xc3, 0xe7, 0x7a, 0xc8, 0x3e, 0x54, 0x1d, + 0x6e, 0x5c, 0xce, 0x7d, 0xb5, 0x44, 0xcc, 0x46, 0x2d, 0x56, 0x7d, 0x59, 0x20, 0xf1, 0x89, 0x03, + 0x75, 0xfa, 0x30, 0xa0, 0x9e, 0x13, 0x9e, 0xf3, 0x9b, 0xcc, 0x35, 0x16, 0x62, 0xb3, 0x2d, 0x91, + 0x31, 0x94, 0xa1, 0xfd, 0x6e, 0x11, 0x9a, 0x31, 0xbe, 0x27, 0xd9, 0x6c, 0x78, 0xaa, 0x11, 0x61, + 0xd3, 0xdd, 0xf1, 0x6c, 0x39, 0xb6, 0x62, 0xa9, 0x46, 0x24, 0x09, 0x37, 0x30, 0xce, 0xc7, 0x06, + 0x70, 0x4f, 0xf7, 0x83, 0xc4, 0x28, 0x0b, 0x07, 0xf0, 0x66, 0x48, 0xc1, 0x18, 0x17, 0xb9, 0x2e, + 0x2f, 0x22, 0x29, 0x27, 0x13, 0xb2, 0x8e, 0xb8, 0x65, 0xa4, 0x32, 0x81, 0x5b, 0x46, 0x48, 0x17, + 0x66, 0x55, 0xab, 0x15, 0xf5, 0x6c, 0xe9, 0x3a, 0xc5, 0xcc, 0x93, 0x82, 0xc0, 0x21, 0x50, 0xed, + 0xfb, 0x05, 0x98, 0x4e, 0x58, 0x14, 0x45, 0x2a, 0x55, 0x75, 0x2a, 0x2d, 0x91, 0x4a, 0x35, 0x76, + 0x98, 0xec, 0x65, 0xa8, 0x8a, 0x0e, 0x4a, 0x07, 0x9b, 0x8b, 0x2e, 0x44, 0x49, 0x65, 0xaa, 0x82, + 0xf4, 0x59, 0xa4, 0x55, 0x05, 0xe9, 0xd4, 0x40, 0x45, 0x17, 0xae, 0x40, 0xd1, 0x3a, 0xd9, 0xd3, + 0x31, 0x57, 0xa0, 0x28, 0xc7, 0x90, 0x43, 0xfb, 0xbb, 0xbc, 0xdd, 0x81, 0x77, 0x14, 0x9a, 0x4a, + 0xba, 0x50, 0x93, 0x01, 0xc6, 0xf2, 0xd3, 0x78, 0x33, 0x87, 0x99, 0x93, 0xe3, 0xc8, 0x10, 0x59, + 0xdd, 0x38, 0xb8, 0xb7, 0xb7, 0x87, 0x0a, 0x9d, 0xdc, 0x84, 0x86, 0xeb, 0xc8, 0x29, 0x59, 0x3e, + 0xfe, 0x17, 0x98, 0x2a, 0x70, 0x4f, 0x15, 0x3e, 0x3a, 0x6e, 0x5d, 0x0e, 0xff, 0x24, 0x1a, 0x89, + 0x51, 0x4d, 0xed, 0x4f, 0x15, 0xe0, 0x05, 0x74, 0x6d, 0xdb, 0x72, 0xba, 0x49, 0x57, 0x36, 0xb1, + 0x61, 0x46, 0xcc, 0x34, 0x87, 0xba, 0x65, 0xeb, 0xbb, 0x36, 0x7d, 0xa2, 0xa9, 0x63, 0x10, 0x58, + 0xf6, 0x82, 0xb8, 0x98, 0x75, 0x61, 0xdd, 0x09, 0xee, 0x79, 0x9d, 0xc0, 0xb3, 0x9c, 0xae, 0x58, + 0xf6, 0x36, 0x13, 0x58, 0x98, 0xc2, 0xd6, 0x7e, 0xaf, 0x04, 0x3c, 0x78, 0x95, 0x7c, 0x19, 0x1a, + 0x3d, 0x6a, 0xec, 0xeb, 0x8e, 0xe5, 0xab, 0xa4, 0xd4, 0x57, 0xd8, 0x73, 0x6d, 0xaa, 0xc2, 0x47, + 0xec, 0x55, 0x2c, 0x77, 0x36, 0xf8, 0x39, 0xb2, 0x88, 0x97, 0x18, 0x50, 0xed, 0xfa, 0xbe, 0xde, + 0xb7, 0x72, 0xc7, 0x0c, 0x89, 0x24, 0xc0, 0x62, 0x3a, 0x12, 0xbf, 0x51, 0x42, 0x13, 0x03, 0x2a, + 0x7d, 0x5b, 0xb7, 0x9c, 0xdc, 0x17, 0x09, 0xb2, 0x27, 0xd8, 0x62, 0x48, 0x62, 0xbd, 0xe3, 0x3f, + 0x51, 0x60, 0x93, 0x01, 0x34, 0x7d, 0xc3, 0xd3, 0x7b, 0xfe, 0xbe, 0xbe, 0xf4, 0xea, 0x6b, 0xb9, + 0x77, 0x73, 0x91, 0x28, 0xa1, 0x5c, 0xae, 0xe0, 0xf2, 0x66, 0xe7, 0xf6, 0xf2, 0xd2, 0xab, 0xaf, + 0x61, 0x5c, 0x4e, 0x5c, 0xec, 0xab, 0xaf, 0x2c, 0xc9, 0x19, 0x64, 0xe2, 0x62, 0x5f, 0x7d, 0x65, + 0x09, 0xe3, 0x72, 0xb4, 0xff, 0x55, 0x80, 0x46, 0xc8, 0x4b, 0x76, 0x00, 0xd8, 0x5c, 0x26, 0xd3, + 0xf6, 0x9e, 0x49, 0x71, 0xe0, 0xe6, 0xbb, 0x9d, 0xb0, 0x32, 0xc6, 0x80, 0x32, 0xf2, 0x1a, 0x17, + 0x27, 0x9d, 0xd7, 0x78, 0x11, 0x1a, 0xfb, 0xba, 0x63, 0xfa, 0xfb, 0xfa, 0x01, 0x95, 0x31, 0xff, + 0xe1, 0xde, 0xf2, 0xb6, 0x22, 0x60, 0xc4, 0xa3, 0xfd, 0xfd, 0x2a, 0x88, 0x40, 0x1f, 0x36, 0xe9, + 0x98, 0x96, 0x2f, 0x4e, 0xe6, 0x14, 0x78, 0xcd, 0x70, 0xd2, 0x59, 0x95, 0xe5, 0x18, 0x72, 0x90, + 0x2b, 0x50, 0xea, 0x59, 0x8e, 0x54, 0x29, 0xb9, 0x65, 0x7e, 0xd3, 0x72, 0x90, 0x95, 0x71, 0x92, + 0xfe, 0x50, 0xaa, 0x8c, 0x82, 0xa4, 0x3f, 0x44, 0x56, 0x46, 0xbe, 0x0a, 0x17, 0x6c, 0xd7, 0x3d, + 0x60, 0xd3, 0x47, 0x3c, 0x76, 0x79, 0x5a, 0xd8, 0xca, 0x36, 0x92, 0x24, 0x4c, 0xf3, 0x92, 0x1d, + 0x78, 0xf1, 0x03, 0xea, 0xb9, 0x72, 0xbe, 0xec, 0xd8, 0x94, 0xf6, 0x15, 0x8c, 0x50, 0x54, 0x78, + 0x68, 0xf5, 0xcf, 0x65, 0xb3, 0xe0, 0xa8, 0xba, 0xfc, 0x30, 0x88, 0xee, 0x75, 0x69, 0xb0, 0xe5, + 0xb9, 0x4c, 0x19, 0xb5, 0x9c, 0xae, 0x82, 0xad, 0x46, 0xb0, 0xdb, 0xd9, 0x2c, 0x38, 0xaa, 0x2e, + 0x79, 0x07, 0xe6, 0x04, 0x49, 0xa8, 0x2d, 0xcb, 0x62, 0x9a, 0xb1, 0x6c, 0x75, 0xff, 0xee, 0xb4, + 0x70, 0x80, 0x6e, 0x8f, 0xe0, 0xc1, 0x91, 0xb5, 0xc9, 0x5b, 0x30, 0xab, 0xdc, 0xdf, 0x5b, 0xd4, + 0xeb, 0x84, 0xc1, 0x5f, 0xd3, 0x2a, 0x06, 0x5e, 0xc5, 0x80, 0x63, 0x8a, 0x0b, 0x87, 0xea, 0x11, + 0x84, 0xcb, 0x3c, 0xc2, 0x6b, 0xa7, 0xbf, 0xe2, 0xba, 0xb6, 0xe9, 0x3e, 0x70, 0xd4, 0xb3, 0x8b, + 0x1d, 0x18, 0xf7, 0x78, 0x77, 0x32, 0x39, 0x70, 0x44, 0x4d, 0xf6, 0xe4, 0x9c, 0xb2, 0xea, 0x3e, + 0x70, 0xd2, 0xa8, 0x10, 0x3d, 0x79, 0x67, 0x04, 0x0f, 0x8e, 0xac, 0x4d, 0xd6, 0x80, 0xa4, 0x9f, + 0x60, 0xa7, 0x2f, 0x63, 0x32, 0x2e, 0x8b, 0x0c, 0x5c, 0x69, 0x2a, 0x66, 0xd4, 0x20, 0x1b, 0x70, + 0x29, 0x5d, 0xca, 0xc4, 0xc9, 0xf0, 0x0c, 0x9e, 0x7b, 0x1b, 0x33, 0xe8, 0x98, 0x59, 0x4b, 0xfb, + 0x07, 0x45, 0x98, 0x4e, 0xa4, 0x6c, 0x79, 0xe6, 0x52, 0x63, 0xb0, 0xdd, 0x60, 0xcf, 0xef, 0xae, + 0xaf, 0xde, 0xa6, 0xba, 0x49, 0x3d, 0x75, 0x22, 0xa8, 0x21, 0x97, 0xc5, 0x04, 0x05, 0x53, 0x9c, + 0x64, 0x0f, 0x2a, 0xc2, 0xf1, 0x93, 0xf7, 0xfa, 0x2e, 0xd5, 0x47, 0xdc, 0xfb, 0x23, 0xef, 0xbc, + 0x73, 0x3d, 0x8a, 0x02, 0x5e, 0x0b, 0x60, 0x2a, 0xce, 0xc1, 0x26, 0x92, 0x48, 0xed, 0xad, 0x25, + 0x54, 0xde, 0x75, 0x28, 0x05, 0xc1, 0xb8, 0x49, 0x37, 0x84, 0x23, 0x71, 0x7b, 0x03, 0x19, 0x86, + 0xb6, 0xc7, 0xde, 0x9d, 0xef, 0x5b, 0xae, 0x23, 0x6f, 0x60, 0xd8, 0x81, 0x9a, 0xdc, 0x0e, 0x8f, + 0x99, 0x34, 0x84, 0xeb, 0x4a, 0xca, 0x8e, 0xae, 0xb0, 0xb4, 0x7f, 0x53, 0x84, 0x46, 0x68, 0xf7, + 0x3a, 0xc5, 0xcd, 0x06, 0x2e, 0x34, 0xc2, 0x08, 0xd5, 0xdc, 0x77, 0x13, 0x47, 0x81, 0x93, 0xdc, + 0x54, 0x13, 0xfe, 0xc5, 0x48, 0x46, 0x3c, 0xfa, 0xb5, 0x94, 0x23, 0xfa, 0xb5, 0x0f, 0xb5, 0xc0, + 0xb3, 0xba, 0x5d, 0xb9, 0x4b, 0xc8, 0x13, 0xfe, 0x1a, 0x76, 0xd7, 0xb6, 0x00, 0x94, 0x3d, 0x2b, + 0xfe, 0xa0, 0x12, 0xa3, 0xbd, 0x0f, 0xb3, 0x69, 0x4e, 0xae, 0x42, 0x1b, 0xfb, 0xd4, 0x1c, 0xd8, + 0xaa, 0x8f, 0x23, 0x15, 0x5a, 0x96, 0x63, 0xc8, 0x41, 0x6e, 0x40, 0x9d, 0xbd, 0xa6, 0x0f, 0x5c, + 0x47, 0xa9, 0xb1, 0x7c, 0x37, 0xb2, 0x2d, 0xcb, 0x30, 0xa4, 0x6a, 0xff, 0xb9, 0x04, 0x57, 0x22, + 0xeb, 0xe5, 0xa6, 0xee, 0xe8, 0xdd, 0x53, 0x5c, 0x48, 0xfb, 0xe9, 0x31, 0xcc, 0xb3, 0x5e, 0x4f, + 0x53, 0x7a, 0x06, 0xae, 0xa7, 0xf9, 0xbf, 0x45, 0xe0, 0xd1, 0xf4, 0xe4, 0xdb, 0x30, 0xa5, 0xc7, + 0xee, 0x22, 0x97, 0xaf, 0xf3, 0x66, 0xee, 0xd7, 0xc9, 0x83, 0xf6, 0x43, 0xc3, 0x4e, 0xbc, 0x14, + 0x13, 0x02, 0x89, 0x0b, 0xf5, 0x3d, 0xdd, 0xb6, 0x99, 0x2e, 0x94, 0xdb, 0x1b, 0x9b, 0x10, 0xce, + 0x87, 0xf9, 0x9a, 0x84, 0xc6, 0x50, 0x08, 0xf9, 0x6e, 0x01, 0xa6, 0xbd, 0xf8, 0x76, 0x4d, 0xbe, + 0x90, 0x3c, 0xb1, 0x3a, 0x31, 0xb4, 0x78, 0xfc, 0x64, 0x7c, 0x4f, 0x98, 0x94, 0xa9, 0xfd, 0xc7, + 0x02, 0x4c, 0x77, 0x6c, 0xcb, 0xb4, 0x9c, 0xee, 0x39, 0xde, 0x8e, 0x73, 0x0f, 0x2a, 0xbe, 0x6d, + 0x99, 0x74, 0xcc, 0xd5, 0x44, 0xac, 0x63, 0x0c, 0x00, 0x05, 0x4e, 0xf2, 0xba, 0x9d, 0xd2, 0x29, + 0xae, 0xdb, 0xf9, 0x4f, 0x35, 0x90, 0xe7, 0x42, 0xc8, 0x00, 0x1a, 0x5d, 0x75, 0x8b, 0x87, 0x7c, + 0xc6, 0xdb, 0x39, 0x32, 0xc0, 0x26, 0xee, 0x03, 0x11, 0x73, 0x7f, 0x58, 0x88, 0x91, 0x24, 0x42, + 0x93, 0x97, 0xe0, 0xaf, 0xe6, 0xbc, 0x04, 0x5f, 0x88, 0x1b, 0xbe, 0x06, 0x5f, 0x87, 0xf2, 0x7e, + 0x10, 0xf4, 0xe5, 0x60, 0x1a, 0xdf, 0x58, 0x18, 0x25, 0x21, 0x13, 0x3a, 0x11, 0xfb, 0x8f, 0x1c, + 0x9a, 0x89, 0x70, 0xf4, 0xf0, 0xaa, 0xd1, 0x95, 0x5c, 0x71, 0x41, 0x71, 0x11, 0xec, 0x3f, 0x72, + 0x68, 0xf2, 0x0b, 0xd0, 0x0c, 0x3c, 0xdd, 0xf1, 0xf7, 0x5c, 0xaf, 0x47, 0x3d, 0xb9, 0x47, 0x5d, + 0xcb, 0x71, 0x0f, 0xfc, 0x76, 0x84, 0x26, 0x6c, 0xec, 0x89, 0x22, 0x8c, 0x4b, 0x23, 0x07, 0x50, + 0x1f, 0x98, 0xa2, 0x61, 0xd2, 0x0c, 0xb6, 0x9c, 0xe7, 0x6a, 0xff, 0x58, 0xd4, 0x8f, 0xfa, 0x87, + 0xa1, 0x80, 0xe4, 0xad, 0xba, 0xb5, 0x49, 0xdd, 0xaa, 0x1b, 0x1f, 0x8d, 0x59, 0x19, 0x92, 0x48, + 0x4f, 0xea, 0xb5, 0x4e, 0x57, 0x06, 0x2d, 0xae, 0xe5, 0x56, 0x39, 0x85, 0xc8, 0x66, 0xa8, 0x1b, + 0x3b, 0x5d, 0x54, 0x32, 0x88, 0x05, 0xd5, 0x3e, 0xb7, 0x3e, 0xe7, 0xbe, 0x61, 0x3d, 0xee, 0x20, + 0x10, 0x73, 0x8d, 0x28, 0x41, 0x29, 0x40, 0xeb, 0x81, 0xf4, 0x3b, 0x12, 0x23, 0x71, 0x69, 0x99, + 0x38, 0x55, 0xbb, 0x78, 0xba, 0xa9, 0x27, 0xbc, 0x3d, 0x2b, 0x76, 0x69, 0x42, 0xe6, 0xed, 0x64, + 0xda, 0xbf, 0x2d, 0x42, 0x69, 0x7b, 0xa3, 0x23, 0x12, 0x21, 0xf3, 0x6b, 0x10, 0x69, 0xe7, 0xc0, + 0xea, 0xdf, 0xa7, 0x9e, 0xb5, 0x77, 0x24, 0x77, 0xf9, 0xb1, 0x44, 0xc8, 0x69, 0x0e, 0xcc, 0xa8, + 0x45, 0xde, 0x85, 0x29, 0x43, 0x5f, 0xa1, 0x5e, 0x30, 0x8e, 0x0d, 0x83, 0xa7, 0x42, 0x58, 0x59, + 0x8e, 0xaa, 0x63, 0x02, 0x8c, 0xec, 0x00, 0x18, 0x11, 0x74, 0xe9, 0xcc, 0x96, 0x97, 0x18, 0x70, + 0x0c, 0x88, 0x20, 0x34, 0x0e, 0x18, 0x2b, 0x47, 0x2d, 0x9f, 0x05, 0x95, 0x0f, 0xd2, 0x3b, 0xaa, + 0x2e, 0x46, 0x30, 0x9a, 0x03, 0xd3, 0x89, 0x9b, 0xcc, 0xc8, 0x57, 0xa0, 0xee, 0xf6, 0x63, 0x33, + 0x77, 0x83, 0x47, 0x62, 0xd7, 0xef, 0xc9, 0xb2, 0x47, 0xc7, 0xad, 0xe9, 0x0d, 0xb7, 0x6b, 0x19, + 0xaa, 0x00, 0x43, 0x76, 0xa2, 0x41, 0x95, 0x9f, 0xf9, 0x55, 0xf7, 0x98, 0xf1, 0xa1, 0xc3, 0xaf, + 0x1a, 0xf2, 0x51, 0x52, 0xb4, 0x5f, 0x2a, 0x43, 0xe4, 0xad, 0x27, 0x3e, 0x54, 0xc5, 0x79, 0x23, + 0xb9, 0x48, 0x9c, 0xeb, 0xd1, 0x26, 0x29, 0x8a, 0x74, 0xa1, 0xf4, 0xbe, 0xbb, 0x9b, 0x7b, 0x8d, + 0x88, 0x25, 0x2e, 0x11, 0x66, 0xb9, 0x58, 0x01, 0x32, 0x09, 0xe4, 0x2f, 0x17, 0xe0, 0x79, 0x3f, + 0xad, 0x65, 0xcb, 0xe1, 0x80, 0xf9, 0xb7, 0x13, 0x69, 0xbd, 0x5d, 0x86, 0xcc, 0x8f, 0x22, 0xe3, + 0x70, 0x5b, 0x58, 0xff, 0x0b, 0x37, 0xba, 0x1c, 0x4e, 0xb7, 0x72, 0xde, 0xd7, 0x9c, 0xec, 0xff, + 0x64, 0x19, 0x4a, 0x51, 0xda, 0x77, 0x8a, 0xd0, 0x8c, 0x2d, 0x0c, 0xb9, 0xaf, 0xc7, 0x7b, 0x98, + 0xba, 0x1e, 0x6f, 0x6b, 0xfc, 0xa8, 0x92, 0xa8, 0x55, 0xe7, 0x7d, 0x43, 0xde, 0x3f, 0x2e, 0x42, + 0x69, 0x67, 0x75, 0x2d, 0xb9, 0x3f, 0x2e, 0x3c, 0x85, 0xfd, 0xf1, 0x3e, 0xd4, 0x76, 0x07, 0x96, + 0x1d, 0x58, 0x4e, 0xee, 0xd4, 0x4a, 0xea, 0x36, 0x41, 0xe9, 0x56, 0x11, 0xa8, 0xa8, 0xe0, 0x49, + 0x17, 0x6a, 0x5d, 0x91, 0xdb, 0x36, 0x77, 0xac, 0xad, 0xcc, 0x91, 0x2b, 0x04, 0xc9, 0x3f, 0xa8, + 0xd0, 0xb5, 0x23, 0xa8, 0xee, 0xac, 0xca, 0x1d, 0xc6, 0xd3, 0xed, 0x4d, 0xed, 0x17, 0x20, 0x54, + 0x38, 0x9e, 0xbe, 0xf0, 0xff, 0x5a, 0x80, 0xa4, 0x8e, 0xf5, 0xf4, 0x47, 0xd3, 0x41, 0x7a, 0x34, + 0xad, 0x4e, 0xe2, 0xe3, 0xcb, 0x1e, 0x50, 0xda, 0xbf, 0x2a, 0x40, 0xea, 0x90, 0x28, 0x79, 0x4d, + 0xa6, 0x49, 0x4c, 0x06, 0x35, 0xaa, 0x34, 0x89, 0x24, 0xc9, 0x1d, 0x4b, 0x97, 0xf8, 0x21, 0xdb, + 0x19, 0xc6, 0x7d, 0x75, 0xb2, 0xf9, 0x77, 0xc7, 0xdf, 0x19, 0x66, 0x79, 0xfe, 0x64, 0xe0, 0x6d, + 0x9c, 0x84, 0x49, 0xb9, 0xda, 0xdf, 0x2b, 0x42, 0xf5, 0xa9, 0xe5, 0xc5, 0xa0, 0x89, 0x58, 0xe8, + 0x95, 0x9c, 0xb3, 0xfd, 0xc8, 0x48, 0xe8, 0x5e, 0x2a, 0x12, 0xfa, 0x66, 0x5e, 0x41, 0x8f, 0x8f, + 0x83, 0xfe, 0x17, 0x05, 0x90, 0x6b, 0xcd, 0xba, 0xe3, 0x07, 0xba, 0x63, 0x50, 0x62, 0x84, 0x0b, + 0x5b, 0xde, 0x80, 0x3b, 0x19, 0x94, 0x2a, 0x74, 0x19, 0xfe, 0x5b, 0x2d, 0x64, 0xe4, 0x8b, 0x50, + 0xdf, 0x77, 0xfd, 0x80, 0x2f, 0x5e, 0xc5, 0xa4, 0x75, 0xee, 0xb6, 0x2c, 0xc7, 0x90, 0x23, 0xed, + 0x39, 0xaf, 0x8c, 0xf6, 0x9c, 0x6b, 0xbf, 0x51, 0x84, 0xa9, 0x4f, 0x4a, 0xe2, 0x8d, 0xac, 0xc8, + 0xf1, 0x52, 0xce, 0xc8, 0xf1, 0xf2, 0x59, 0x22, 0xc7, 0xb5, 0x1f, 0x16, 0x00, 0x9e, 0x5a, 0xd6, + 0x0f, 0x33, 0x19, 0xd4, 0x9d, 0x7b, 0x5c, 0x65, 0x87, 0x74, 0xff, 0xed, 0x8a, 0x7a, 0x24, 0x1e, + 0xd0, 0xfd, 0x61, 0x01, 0x66, 0xf4, 0x44, 0x90, 0x74, 0x6e, 0x7d, 0x39, 0x15, 0x73, 0x1d, 0xc6, + 0xf8, 0x25, 0xcb, 0x31, 0x25, 0x96, 0xbc, 0x1e, 0x65, 0xe8, 0xbf, 0x1b, 0x0d, 0xfb, 0xa1, 0xd4, + 0xfa, 0x22, 0xaa, 0x2b, 0xce, 0xf9, 0x84, 0xa0, 0xf4, 0xd2, 0x44, 0x82, 0xd2, 0xe3, 0xc7, 0x6d, + 0xcb, 0x8f, 0x3d, 0x6e, 0x7b, 0x08, 0x8d, 0x3d, 0xcf, 0xed, 0xf1, 0xb8, 0x6f, 0x79, 0x07, 0xfe, + 0xcd, 0x1c, 0x0b, 0x65, 0x6f, 0xd7, 0x72, 0xa8, 0xc9, 0x63, 0xca, 0x43, 0x1b, 0xd9, 0x9a, 0xc2, + 0xc7, 0x48, 0x14, 0x77, 0x2b, 0xb8, 0x42, 0x6a, 0x75, 0x92, 0x52, 0xc3, 0xb9, 0x64, 0x5b, 0xa0, + 0xa3, 0x12, 0x93, 0x8c, 0xf5, 0xae, 0x3d, 0x9d, 0x58, 0x6f, 0xed, 0xcf, 0xd6, 0xd4, 0x04, 0xf6, + 0xcc, 0x25, 0x83, 0xfe, 0x34, 0x49, 0x42, 0x97, 0x0e, 0x65, 0x30, 0xa8, 0x3f, 0xc5, 0x0c, 0x06, + 0x8d, 0xc9, 0x64, 0x30, 0x80, 0x7c, 0x19, 0x0c, 0x9a, 0x13, 0xca, 0x60, 0x30, 0x35, 0xa9, 0x0c, + 0x06, 0xd3, 0x63, 0x65, 0x30, 0x98, 0x39, 0x55, 0x06, 0x83, 0xe3, 0x12, 0xa4, 0x36, 0xe3, 0x9f, + 0xfa, 0xf8, 0xfe, 0x50, 0xf9, 0xf8, 0xbe, 0x57, 0x84, 0x68, 0x22, 0x3e, 0x63, 0x0c, 0xd4, 0x3b, + 0x3c, 0x50, 0x9a, 0x07, 0xdd, 0xe7, 0xb9, 0x43, 0x7d, 0x53, 0x62, 0x60, 0x88, 0x46, 0x7c, 0x00, + 0x2b, 0xbc, 0xc7, 0x24, 0xb7, 0xb7, 0x24, 0xba, 0x12, 0x45, 0x18, 0x49, 0xa3, 0xff, 0x18, 0x13, + 0xa3, 0xfd, 0xf3, 0x22, 0xc8, 0x0b, 0x6f, 0x08, 0x85, 0xca, 0x9e, 0xf5, 0x90, 0x9a, 0xb9, 0x23, + 0xab, 0xd7, 0x18, 0x8a, 0xbc, 0x55, 0x87, 0xbb, 0x83, 0x78, 0x01, 0x0a, 0x74, 0x6e, 0xe7, 0x17, + 0xee, 0x3d, 0xd9, 0x7f, 0x39, 0xec, 0xfc, 0x71, 0x37, 0xa1, 0xb4, 0xf3, 0x8b, 0x22, 0x54, 0x32, + 0x84, 0x5b, 0x81, 0x47, 0x7a, 0xe4, 0xf6, 0x66, 0x26, 0x22, 0x46, 0x94, 0x5b, 0xc1, 0x17, 0x29, + 0x4c, 0xa4, 0x8c, 0xf6, 0xcf, 0xff, 0xe0, 0x47, 0xd7, 0x9e, 0xfb, 0xe1, 0x8f, 0xae, 0x3d, 0xf7, + 0xd1, 0x8f, 0xae, 0x3d, 0xf7, 0x4b, 0x27, 0xd7, 0x0a, 0x3f, 0x38, 0xb9, 0x56, 0xf8, 0xe1, 0xc9, + 0xb5, 0xc2, 0x47, 0x27, 0xd7, 0x0a, 0xff, 0xfe, 0xe4, 0x5a, 0xe1, 0x2f, 0xfc, 0x87, 0x6b, 0xcf, + 0xfd, 0xdc, 0x97, 0xa3, 0x26, 0x2c, 0xaa, 0x26, 0x2c, 0x2a, 0x81, 0x8b, 0xfd, 0x83, 0xee, 0x22, + 0x6b, 0x42, 0x54, 0xa2, 0x9a, 0xf0, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x94, 0x34, 0x30, 0x66, + 0x45, 0xa2, 0x00, 0x00, } func (m *AbstractPodTemplate) Marshal() (dAtA []byte, err error) { @@ -7621,6 +7687,99 @@ func (m *Probe) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *PulsarAuth) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PulsarAuth) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PulsarAuth) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Token != nil { + { + size, err := m.Token.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PulsarSource) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PulsarSource) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PulsarSource) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Auth != nil { + { + size, err := m.Auth.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + i = encodeVarintGenerated(dAtA, i, uint64(m.MaxUnack)) + i-- + dAtA[i] = 0x28 + i -= len(m.SubscriptionName) + copy(dAtA[i:], m.SubscriptionName) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.SubscriptionName))) + i-- + dAtA[i] = 0x22 + i -= len(m.ConsumerName) + copy(dAtA[i:], m.ConsumerName) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.ConsumerName))) + i-- + dAtA[i] = 0x1a + i -= len(m.Topic) + copy(dAtA[i:], m.Topic) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Topic))) + i-- + dAtA[i] = 0x12 + i -= len(m.ServerAddr) + copy(dAtA[i:], m.ServerAddr) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.ServerAddr))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func (m *RedisBufferService) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -8501,6 +8660,18 @@ func (m *Source) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Pulsar != nil { + { + size, err := m.Pulsar.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + } if m.Serving != nil { { size, err := m.Serving.MarshalToSizedBuffer(dAtA[:i]) @@ -11198,6 +11369,41 @@ func (m *Probe) Size() (n int) { return n } +func (m *PulsarAuth) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Token != nil { + l = m.Token.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + +func (m *PulsarSource) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ServerAddr) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Topic) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.ConsumerName) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.SubscriptionName) + n += 1 + l + sovGenerated(uint64(l)) + n += 1 + sovGenerated(uint64(m.MaxUnack)) + if m.Auth != nil { + l = m.Auth.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + func (m *RedisBufferService) Size() (n int) { if m == nil { return 0 @@ -11561,6 +11767,10 @@ func (m *Source) Size() (n int) { l = m.Serving.Size() n += 1 + l + sovGenerated(uint64(l)) } + if m.Pulsar != nil { + l = m.Pulsar.Size() + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -13023,6 +13233,31 @@ func (this *Probe) String() string { }, "") return s } +func (this *PulsarAuth) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PulsarAuth{`, + `Token:` + strings.Replace(fmt.Sprintf("%v", this.Token), "SecretKeySelector", "v1.SecretKeySelector", 1) + `,`, + `}`, + }, "") + return s +} +func (this *PulsarSource) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PulsarSource{`, + `ServerAddr:` + fmt.Sprintf("%v", this.ServerAddr) + `,`, + `Topic:` + fmt.Sprintf("%v", this.Topic) + `,`, + `ConsumerName:` + fmt.Sprintf("%v", this.ConsumerName) + `,`, + `SubscriptionName:` + fmt.Sprintf("%v", this.SubscriptionName) + `,`, + `MaxUnack:` + fmt.Sprintf("%v", this.MaxUnack) + `,`, + `Auth:` + strings.Replace(this.Auth.String(), "PulsarAuth", "PulsarAuth", 1) + `,`, + `}`, + }, "") + return s +} func (this *RedisBufferService) String() string { if this == nil { return "nil" @@ -13242,6 +13477,7 @@ func (this *Source) String() string { `UDSource:` + strings.Replace(this.UDSource.String(), "UDSource", "UDSource", 1) + `,`, `JetStream:` + strings.Replace(this.JetStream.String(), "JetStreamSource", "JetStreamSource", 1) + `,`, `Serving:` + strings.Replace(this.Serving.String(), "ServingSource", "ServingSource", 1) + `,`, + `Pulsar:` + strings.Replace(this.Pulsar.String(), "PulsarSource", "PulsarSource", 1) + `,`, `}`, }, "") return s @@ -27159,7 +27395,7 @@ func (m *Probe) Unmarshal(dAtA []byte) error { } return nil } -func (m *RedisBufferService) Unmarshal(dAtA []byte) error { +func (m *PulsarAuth) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -27182,15 +27418,15 @@ func (m *RedisBufferService) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RedisBufferService: wiretype end group for non-group") + return fmt.Errorf("proto: PulsarAuth: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RedisBufferService: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: PulsarAuth: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Native", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Token", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -27217,20 +27453,339 @@ func (m *RedisBufferService) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Native == nil { - m.Native = &NativeRedis{} + if m.Token == nil { + m.Token = &v1.SecretKeySelector{} } - if err := m.Native.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Token.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field External", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PulsarSource) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PulsarSource: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PulsarSource: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ServerAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + 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 ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ServerAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Topic", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + 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 ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Topic = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsumerName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + 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 ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ConsumerName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SubscriptionName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + 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 ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SubscriptionName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxUnack", wireType) + } + m.MaxUnack = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxUnack |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Auth", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Auth == nil { + m.Auth = &PulsarAuth{} + } + if err := m.Auth.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RedisBufferService) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RedisBufferService: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RedisBufferService: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Native", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Native == nil { + m.Native = &NativeRedis{} + } + if err := m.Native.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field External", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { return ErrIntOverflowGenerated } if iNdEx >= l { @@ -30022,6 +30577,42 @@ func (m *Source) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pulsar", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pulsar == nil { + m.Pulsar = &PulsarSource{} + } + if err := m.Pulsar.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) diff --git a/pkg/apis/numaflow/v1alpha1/generated.proto b/pkg/apis/numaflow/v1alpha1/generated.proto index dfe8339b6b..7b81e2235e 100644 --- a/pkg/apis/numaflow/v1alpha1/generated.proto +++ b/pkg/apis/numaflow/v1alpha1/generated.proto @@ -1314,6 +1314,30 @@ message Probe { optional int32 failureThreshold = 5; } +// PulsarAuth defines how to authenticate with Pulsar +message PulsarAuth { + // JWT Token auth + // +optional + optional .k8s.io.api.core.v1.SecretKeySelector token = 1; +} + +message PulsarSource { + optional string serverAddr = 1; + + optional string topic = 2; + + optional string consumerName = 3; + + optional string subscriptionName = 4; + + // Maximum number of messages that are in not yet acked state. Once this limit is crossed, futher read requests will return empty list. + optional uint32 maxUnack = 5; + + // Auth information + // +optional + optional PulsarAuth auth = 6; +} + message RedisBufferService { // Native brings up a native Redis service optional NativeRedis native = 1; @@ -1607,6 +1631,9 @@ message Source { // +optional optional ServingSource serving = 8; + + // +optional + optional PulsarSource pulsar = 9; } // Status is a common structure which can be used for Status field. diff --git a/pkg/apis/numaflow/v1alpha1/pulsar_auth.go b/pkg/apis/numaflow/v1alpha1/pulsar_auth.go new file mode 100644 index 0000000000..9e6d719e08 --- /dev/null +++ b/pkg/apis/numaflow/v1alpha1/pulsar_auth.go @@ -0,0 +1,26 @@ +/* +Copyright 2022 The Numaproj Authors. + +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. +*/ + +package v1alpha1 + +import corev1 "k8s.io/api/core/v1" + +// PulsarAuth defines how to authenticate with Pulsar +type PulsarAuth struct { + // JWT Token auth + // +optional + Token *corev1.SecretKeySelector `json:"token,omitempty" protobuf:"bytes,1,opt,name=token"` +} diff --git a/pkg/apis/numaflow/v1alpha1/pulsar_source.go b/pkg/apis/numaflow/v1alpha1/pulsar_source.go new file mode 100644 index 0000000000..1b4d5adb21 --- /dev/null +++ b/pkg/apis/numaflow/v1alpha1/pulsar_source.go @@ -0,0 +1,29 @@ +/* +Copyright 2022 The Numaproj Authors. + +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. +*/ + +package v1alpha1 + +type PulsarSource struct { + ServerAddr string `json:"serverAddr" protobuf:"bytes,1,name=server_addr"` + Topic string `json:"topic" protobuf:"bytes,2,name=topic"` + ConsumerName string `json:"consumerName" protobuf:"bytes,3,name=consumerName"` + SubscriptionName string `json:"subscriptionName" protobuf:"bytes,4,name=subscriptionName"` + // Maximum number of messages that are in not yet acked state. Once this limit is crossed, futher read requests will return empty list. + MaxUnack uint32 `json:"maxUnack,omitempty" protobuf:"bytes,5,opt,name=maxUnack"` + // Auth information + // +optional + Auth *PulsarAuth `json:"auth,omitempty" protobuf:"bytes,6,opt,name=auth"` +} diff --git a/pkg/apis/numaflow/v1alpha1/source.go b/pkg/apis/numaflow/v1alpha1/source.go index e1308cf28e..0873076102 100644 --- a/pkg/apis/numaflow/v1alpha1/source.go +++ b/pkg/apis/numaflow/v1alpha1/source.go @@ -43,6 +43,8 @@ type Source struct { JetStream *JetStreamSource `json:"jetstream,omitempty" protobuf:"bytes,7,opt,name=jetstream"` // +optional Serving *ServingSource `json:"serving,omitempty" protobuf:"bytes,8,opt,name=serving"` + // +optional + Pulsar *PulsarSource `json:"pulsar,omitempty" protobuf:"bytes,9,opt,name=pulsar"` } func (s Source) getContainers(req getContainerReq) ([]corev1.Container, []corev1.Container, error) { diff --git a/pkg/apis/numaflow/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/numaflow/v1alpha1/zz_generated.deepcopy.go index 2576898f49..ee979ab2bc 100644 --- a/pkg/apis/numaflow/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/numaflow/v1alpha1/zz_generated.deepcopy.go @@ -2006,6 +2006,48 @@ func (in *Probe) DeepCopy() *Probe { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PulsarAuth) DeepCopyInto(out *PulsarAuth) { + *out = *in + if in.Token != nil { + in, out := &in.Token, &out.Token + *out = new(v1.SecretKeySelector) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PulsarAuth. +func (in *PulsarAuth) DeepCopy() *PulsarAuth { + if in == nil { + return nil + } + out := new(PulsarAuth) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PulsarSource) DeepCopyInto(out *PulsarSource) { + *out = *in + if in.Auth != nil { + in, out := &in.Auth, &out.Auth + *out = new(PulsarAuth) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PulsarSource. +func (in *PulsarSource) DeepCopy() *PulsarSource { + if in == nil { + return nil + } + out := new(PulsarSource) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisBufferService) DeepCopyInto(out *RedisBufferService) { *out = *in @@ -2510,6 +2552,11 @@ func (in *Source) DeepCopyInto(out *Source) { *out = new(ServingSource) (*in).DeepCopyInto(*out) } + if in.Pulsar != nil { + in, out := &in.Pulsar, &out.Pulsar + *out = new(PulsarSource) + (*in).DeepCopyInto(*out) + } return } diff --git a/pkg/apis/numaflow/v1alpha1/zz_generated.openapi.go b/pkg/apis/numaflow/v1alpha1/zz_generated.openapi.go index 1cd2d83b7f..b5cff624f8 100644 --- a/pkg/apis/numaflow/v1alpha1/zz_generated.openapi.go +++ b/pkg/apis/numaflow/v1alpha1/zz_generated.openapi.go @@ -89,6 +89,8 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.PipelineSpec": schema_pkg_apis_numaflow_v1alpha1_PipelineSpec(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.PipelineStatus": schema_pkg_apis_numaflow_v1alpha1_PipelineStatus(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.Probe": schema_pkg_apis_numaflow_v1alpha1_Probe(ref), + "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.PulsarAuth": schema_pkg_apis_numaflow_v1alpha1_PulsarAuth(ref), + "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.PulsarSource": schema_pkg_apis_numaflow_v1alpha1_PulsarSource(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.RedisBufferService": schema_pkg_apis_numaflow_v1alpha1_RedisBufferService(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.RedisConfig": schema_pkg_apis_numaflow_v1alpha1_RedisConfig(ref), "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.RedisSettings": schema_pkg_apis_numaflow_v1alpha1_RedisSettings(ref), @@ -4310,6 +4312,83 @@ func schema_pkg_apis_numaflow_v1alpha1_Probe(ref common.ReferenceCallback) commo } } +func schema_pkg_apis_numaflow_v1alpha1_PulsarAuth(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "PulsarAuth defines how to authenticate with Pulsar", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "token": { + SchemaProps: spec.SchemaProps{ + Description: "JWT Token auth", + Ref: ref("k8s.io/api/core/v1.SecretKeySelector"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/api/core/v1.SecretKeySelector"}, + } +} + +func schema_pkg_apis_numaflow_v1alpha1_PulsarSource(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "serverAddr": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "topic": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "consumerName": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "subscriptionName": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "maxUnack": { + SchemaProps: spec.SchemaProps{ + Description: "Maximum number of messages that are in not yet acked state. Once this limit is crossed, futher read requests will return empty list.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "auth": { + SchemaProps: spec.SchemaProps{ + Description: "Auth information", + Ref: ref("github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.PulsarAuth"), + }, + }, + }, + Required: []string{"serverAddr", "topic", "consumerName", "subscriptionName"}, + }, + }, + Dependencies: []string{ + "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.PulsarAuth"}, + } +} + func schema_pkg_apis_numaflow_v1alpha1_RedisBufferService(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -5120,11 +5199,16 @@ func schema_pkg_apis_numaflow_v1alpha1_Source(ref common.ReferenceCallback) comm Ref: ref("github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.ServingSource"), }, }, + "pulsar": { + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.PulsarSource"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.GeneratorSource", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.HTTPSource", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.JetStreamSource", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.KafkaSource", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.NatsSource", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.ServingSource", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.UDSource", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.UDTransformer"}, + "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.GeneratorSource", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.HTTPSource", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.JetStreamSource", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.KafkaSource", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.NatsSource", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.PulsarSource", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.ServingSource", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.UDSource", "github.com/numaproj/numaflow/pkg/apis/numaflow/v1alpha1.UDTransformer"}, } } diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 48a609ce9e..a6493870a6 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -77,7 +77,7 @@ dependencies = [ "serde_json", "serde_nanos", "serde_repr", - "thiserror", + "thiserror 1.0.64", "time", "tokio", "tokio-rustls 0.26.0", @@ -110,7 +110,7 @@ dependencies = [ "serde_json", "serde_nanos", "serde_repr", - "thiserror", + "thiserror 1.0.64", "time", "tokio", "tokio-rustls 0.26.0", @@ -139,7 +139,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.89", ] [[package]] @@ -150,7 +150,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.89", ] [[package]] @@ -255,7 +255,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.89", ] [[package]] @@ -323,6 +323,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bindgen" version = "0.69.4" @@ -336,16 +345,22 @@ dependencies = [ "lazy_static", "lazycell", "log", - "prettyplease", + "prettyplease 0.2.22", "proc-macro2", "quote", "regex", "rustc-hash 1.1.0", "shlex", - "syn", + "syn 2.0.89", "which", ] +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -384,9 +399,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" dependencies = [ "serde", ] @@ -546,6 +561,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crunchy" version = "0.2.2" @@ -585,7 +615,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.89", ] [[package]] @@ -794,7 +824,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.89", ] [[package]] @@ -809,6 +839,12 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + [[package]] name = "futures-util" version = "0.3.31" @@ -940,6 +976,12 @@ dependencies = [ "http 1.1.0", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "heck" version = "0.5.0" @@ -1219,6 +1261,15 @@ version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.1" @@ -1284,7 +1335,7 @@ dependencies = [ "pest_derive", "regex", "serde_json", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -1341,7 +1392,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-util", "tower 0.4.13", @@ -1362,7 +1413,7 @@ dependencies = [ "serde", "serde-value", "serde_json", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -1491,6 +1542,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + [[package]] name = "multimap" version = "0.10.0" @@ -1597,11 +1654,11 @@ dependencies = [ "chrono", "futures-util", "hyper-util", - "prost", - "prost-types", + "prost 0.13.3", + "prost-types 0.13.3", "serde", "serde_json", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-stream", "tokio-util", @@ -1629,12 +1686,14 @@ dependencies = [ "numaflow 0.1.1", "numaflow-models", "numaflow-pb", + "numaflow-pulsar", "parking_lot", "pep440_rs", "pin-project", "prometheus-client", - "prost", - "prost-types", + "prost 0.13.3", + "prost-types 0.13.3", + "pulsar", "rand", "rcgen", "rustls 0.23.14", @@ -1642,16 +1701,14 @@ dependencies = [ "serde", "serde_json", "tempfile", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-stream", "tokio-util", "tonic", "tower 0.4.13", "tracing", - "tracing-subscriber", "trait-variant", - "uuid", ] [[package]] @@ -1672,13 +1729,29 @@ dependencies = [ name = "numaflow-pb" version = "0.1.0" dependencies = [ - "prost", - "prost-build", - "prost-types", + "prost 0.13.3", + "prost-build 0.13.3", + "prost-types 0.13.3", "tonic", "tonic-build", ] +[[package]] +name = "numaflow-pulsar" +version = "0.1.0" +dependencies = [ + "bincode", + "bytes", + "chrono", + "prost 0.11.9", + "pulsar", + "serde", + "thiserror 2.0.3", + "tokio", + "tonic", + "tracing", +] + [[package]] name = "object" version = "0.36.5" @@ -1803,7 +1876,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9" dependencies = [ "memchr", - "thiserror", + "thiserror 1.0.64", "ucd-trie", ] @@ -1827,7 +1900,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn", + "syn 2.0.89", ] [[package]] @@ -1868,7 +1941,7 @@ checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.89", ] [[package]] @@ -1914,6 +1987,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.109", +] + [[package]] name = "prettyplease" version = "0.2.22" @@ -1921,14 +2004,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ "proc-macro2", - "syn", + "syn 2.0.89", ] [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -1953,7 +2036,17 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.89", +] + +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive 0.11.9", ] [[package]] @@ -1963,7 +2056,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.13.3", +] + +[[package]] +name = "prost-build" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +dependencies = [ + "bytes", + "heck 0.4.1", + "itertools 0.10.5", + "lazy_static", + "log", + "multimap 0.8.3", + "petgraph", + "prettyplease 0.1.25", + "prost 0.11.9", + "prost-types 0.11.9", + "regex", + "syn 1.0.109", + "tempfile", + "which", ] [[package]] @@ -1973,20 +2088,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" dependencies = [ "bytes", - "heck", + "heck 0.5.0", "itertools 0.13.0", "log", - "multimap", + "multimap 0.10.0", "once_cell", "petgraph", - "prettyplease", - "prost", - "prost-types", + "prettyplease 0.2.22", + "prost 0.13.3", + "prost-types 0.13.3", "regex", - "syn", + "syn 2.0.89", "tempfile", ] +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "prost-derive" version = "0.13.3" @@ -1997,7 +2125,16 @@ dependencies = [ "itertools 0.13.0", "proc-macro2", "quote", - "syn", + "syn 2.0.89", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost 0.11.9", ] [[package]] @@ -2006,7 +2143,38 @@ version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" dependencies = [ - "prost", + "prost 0.13.3", +] + +[[package]] +name = "pulsar" +version = "6.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7f3541ff84e39da334979ac4bf171e0f277f4f782603aeae65bf5795dc7275a" +dependencies = [ + "async-trait", + "bit-vec", + "bytes", + "chrono", + "crc", + "futures", + "futures-io", + "futures-timer", + "log", + "nom", + "pem", + "prost 0.11.9", + "prost-build 0.11.9", + "prost-derive 0.11.9", + "rand", + "regex", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", + "tokio-util", + "url", + "uuid", + "webpki-roots 0.25.4", ] [[package]] @@ -2022,7 +2190,7 @@ dependencies = [ "rustc-hash 2.0.0", "rustls 0.23.14", "socket2", - "thiserror", + "thiserror 1.0.64", "tokio", "tracing", ] @@ -2039,7 +2207,7 @@ dependencies = [ "rustc-hash 2.0.0", "rustls 0.23.14", "slab", - "thiserror", + "thiserror 1.0.64", "tinyvec", "tracing", ] @@ -2526,9 +2694,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] @@ -2545,13 +2713,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.89", ] [[package]] @@ -2593,7 +2761,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.89", ] [[package]] @@ -2663,7 +2831,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "thiserror", + "thiserror 1.0.64", "tokio", "tower 0.4.13", "tower-http", @@ -2796,9 +2964,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.79" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", @@ -2860,7 +3039,16 @@ version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.64", +] + +[[package]] +name = "thiserror" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +dependencies = [ + "thiserror-impl 2.0.3", ] [[package]] @@ -2871,7 +3059,18 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.89", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", ] [[package]] @@ -2941,9 +3140,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -2965,7 +3164,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.89", ] [[package]] @@ -3078,7 +3277,7 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "prost", + "prost 0.13.3", "socket2", "tokio", "tokio-stream", @@ -3094,12 +3293,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" dependencies = [ - "prettyplease", + "prettyplease 0.2.22", "proc-macro2", - "prost-build", - "prost-types", + "prost-build 0.13.3", + "prost-types 0.13.3", "quote", - "syn", + "syn 2.0.89", ] [[package]] @@ -3190,7 +3389,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.89", ] [[package]] @@ -3240,7 +3439,7 @@ checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.89", ] [[package]] @@ -3350,6 +3549,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom", + "rand", "serde", ] @@ -3402,7 +3602,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 2.0.89", "wasm-bindgen-shared", ] @@ -3436,7 +3636,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.89", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3748,7 +3948,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.89", ] [[package]] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 99df3be31d..b9a11c653f 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -5,6 +5,7 @@ workspace = { members = [ "serving", "numaflow-core", "numaflow-pb", + "numaflow-extns/pulsar", ] } [[bin]] @@ -16,7 +17,6 @@ name = "numaflow" version = "0.1.0" edition = "2021" - [dependencies] tokio = "1.39.2" backoff = { path = "backoff" } diff --git a/rust/numaflow-core/Cargo.toml b/rust/numaflow-core/Cargo.toml index 179da28dd8..6df96fb14d 100644 --- a/rust/numaflow-core/Cargo.toml +++ b/rust/numaflow-core/Cargo.toml @@ -5,7 +5,8 @@ edition = "2021" [features] nats-tests = [] -all-tests = ["nats-tests"] +pulsar-tests = [] +all-tests = ["nats-tests", "pulsar-tests"] [dependencies] axum = "0.7.5" @@ -21,10 +22,8 @@ prost = "0.13.2" prost-types = "0.13.1" chrono = "0.4.31" base64 = "0.22.1" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } hyper-util = "0.1.6" tower = "0.4.13" -uuid = { version = "1.10.0", features = ["v4"] } serde_json = "1.0.122" numaflow-models = { path = "../numaflow-models" } numaflow-pb = { path = "../numaflow-pb" } @@ -43,10 +42,12 @@ futures = "0.3.30" pin-project = "1.1.5" rand = "0.8.5" async-nats = "0.37.0" +numaflow-pulsar = {path = "../numaflow-extns/pulsar"} [dev-dependencies] tempfile = "3.11.0" numaflow = { git = "https://github.com/numaproj/numaflow-rs.git", rev = "ddd879588e11455921f1ca958ea2b3c076689293" } +pulsar = {version = "6.3.0", default-features = false, features = ["tokio-rustls-runtime"]} [build-dependencies] diff --git a/rust/numaflow-core/src/config/components.rs b/rust/numaflow-core/src/config/components.rs index ce62407f11..840ad39e59 100644 --- a/rust/numaflow-core/src/config/components.rs +++ b/rust/numaflow-core/src/config/components.rs @@ -3,14 +3,14 @@ pub(crate) mod source { const DEFAULT_SOURCE_SOCKET: &str = "/var/run/numaflow/source.sock"; const DEFAULT_SOURCE_SERVER_INFO_FILE: &str = "/var/run/numaflow/sourcer-server-info"; - use std::time::Duration; - - use bytes::Bytes; - use numaflow_models::models::Source; - use tracing::warn; + use std::{fmt::Debug, time::Duration}; use crate::error::Error; use crate::Result; + use bytes::Bytes; + use numaflow_models::models::{GeneratorSource, PulsarSource, Source}; + use numaflow_pulsar::source::{PulsarAuth, PulsarSourceConfig}; + use tracing::warn; #[derive(Debug, Clone, PartialEq)] pub(crate) struct SourceConfig { @@ -29,51 +29,87 @@ pub(crate) mod source { pub(crate) enum SourceType { Generator(GeneratorConfig), UserDefined(UserDefinedConfig), + Pulsar(PulsarSourceConfig), + } + + impl From> for SourceType { + fn from(generator: Box) -> Self { + let mut generator_config = GeneratorConfig::default(); + + if let Some(value_blob) = &generator.value_blob { + generator_config.content = Bytes::from(value_blob.clone()); + } + + if let Some(msg_size) = generator.msg_size { + if msg_size >= 0 { + generator_config.msg_size_bytes = msg_size as u32; + } else { + warn!("'msgSize' cannot be negative, using default value (8 bytes)"); + } + } + + generator_config.value = generator.value; + generator_config.rpu = generator.rpu.unwrap_or(1) as usize; + generator_config.duration = + generator.duration.map_or(Duration::from_millis(1000), |d| { + std::time::Duration::from(d) + }); + generator_config.key_count = generator + .key_count + .map_or(0, |kc| std::cmp::min(kc, u8::MAX as i32) as u8); + generator_config.jitter = generator + .jitter + .map_or(Duration::from_secs(0), std::time::Duration::from); + + SourceType::Generator(generator_config) + } + } + + impl TryFrom> for SourceType { + type Error = Error; + fn try_from(value: Box) -> Result { + let auth: Option = match value.auth { + Some(auth) => 'out: { + let Some(token) = auth.token else { + tracing::warn!("JWT Token authentication is specified, but token is empty"); + break 'out None; + }; + let secret = + crate::shared::utils::get_secret_from_volume(&token.name, &token.key) + .unwrap(); + Some(PulsarAuth::JWT(secret)) + } + None => None, + }; + let pulsar_config = PulsarSourceConfig { + pulsar_server_addr: value.server_addr, + topic: value.topic, + consumer_name: value.consumer_name, + subscription: value.subscription_name, + max_unack: value.max_unack.unwrap_or(1000) as usize, + auth, + }; + Ok(SourceType::Pulsar(pulsar_config)) + } } impl TryFrom> for SourceType { type Error = Error; - fn try_from(source: Box) -> Result { - source - .udsource - .as_ref() - .map(|_| Ok(SourceType::UserDefined(UserDefinedConfig::default()))) - .or_else(|| { - source.generator.as_ref().map(|generator| { - let mut generator_config = GeneratorConfig::default(); - - if let Some(value_blob) = &generator.value_blob { - generator_config.content = Bytes::from(value_blob.clone()); - } - - if let Some(msg_size) = generator.msg_size { - if msg_size >= 0 { - generator_config.msg_size_bytes = msg_size as u32; - } else { - warn!( - "'msgSize' cannot be negative, using default value (8 bytes)" - ); - } - } - - generator_config.value = generator.value; - generator_config.rpu = generator.rpu.unwrap_or(1) as usize; - generator_config.duration = - generator.duration.map_or(Duration::from_millis(1000), |d| { - std::time::Duration::from(d) - }); - generator_config.key_count = generator - .key_count - .map_or(0, |kc| std::cmp::min(kc, u8::MAX as i32) as u8); - generator_config.jitter = generator - .jitter - .map_or(Duration::from_secs(0), std::time::Duration::from); - - Ok(SourceType::Generator(generator_config)) - }) - }) - .ok_or_else(|| Error::Config("Source type not found".to_string()))? + fn try_from(mut source: Box) -> Result { + if let Some(generator) = source.generator.take() { + return Ok(generator.into()); + } + + if source.udsource.is_some() { + return Ok(SourceType::UserDefined(UserDefinedConfig::default())); + } + + if let Some(pulsar) = source.pulsar.take() { + return pulsar.try_into(); + } + + Err(Error::Config(format!("Invalid source type: {source:?}"))) } } diff --git a/rust/numaflow-core/src/config/pipeline.rs b/rust/numaflow-core/src/config/pipeline.rs index 45d1f59c66..4767c0aa70 100644 --- a/rust/numaflow-core/src/config/pipeline.rs +++ b/rust/numaflow-core/src/config/pipeline.rs @@ -284,6 +284,8 @@ impl PipelineConfig { #[cfg(test)] mod tests { + use numaflow_pulsar::source::PulsarSourceConfig; + use super::*; use crate::config::components::sink::{BlackholeConfig, LogConfig, SinkType}; use crate::config::components::source::{GeneratorConfig, SourceType}; @@ -426,4 +428,56 @@ mod tests { assert_eq!(pipeline_config, expected); } + + #[test] + fn test_pipeline_config_pulsar_source() { + let pipeline_cfg_base64 = "eyJtZXRhZGF0YSI6eyJuYW1lIjoic2ltcGxlLXBpcGVsaW5lLWluIiwibmFtZXNwYWNlIjoiZGVmYXVsdCIsImNyZWF0aW9uVGltZXN0YW1wIjpudWxsfSwic3BlYyI6eyJuYW1lIjoiaW4iLCJzb3VyY2UiOnsicHVsc2FyIjp7InNlcnZlckFkZHIiOiJwdWxzYXI6Ly9wdWxzYXItc2VydmljZTo2NjUwIiwidG9waWMiOiJ0ZXN0X3BlcnNpc3RlbnQiLCJjb25zdW1lck5hbWUiOiJteV9wZXJzaXN0ZW50X2NvbnN1bWVyIiwic3Vic2NyaXB0aW9uTmFtZSI6Im15X3BlcnNpc3RlbnRfc3Vic2NyaXB0aW9uIn19LCJsaW1pdHMiOnsicmVhZEJhdGNoU2l6ZSI6NTAsInJlYWRUaW1lb3V0IjoiMXMiLCJidWZmZXJNYXhMZW5ndGgiOjMwMDAwLCJidWZmZXJVc2FnZUxpbWl0Ijo4MH0sInNjYWxlIjp7Im1pbiI6MSwibWF4IjoxfSwidXBkYXRlU3RyYXRlZ3kiOnsidHlwZSI6IlJvbGxpbmdVcGRhdGUiLCJyb2xsaW5nVXBkYXRlIjp7Im1heFVuYXZhaWxhYmxlIjoiMjUlIn19LCJwaXBlbGluZU5hbWUiOiJzaW1wbGUtcGlwZWxpbmUiLCJpbnRlclN0ZXBCdWZmZXJTZXJ2aWNlTmFtZSI6IiIsInJlcGxpY2FzIjowLCJ0b0VkZ2VzIjpbeyJmcm9tIjoiaW4iLCJ0byI6Im91dCIsImNvbmRpdGlvbnMiOm51bGwsImZyb21WZXJ0ZXhUeXBlIjoiU291cmNlIiwiZnJvbVZlcnRleFBhcnRpdGlvbkNvdW50IjoxLCJmcm9tVmVydGV4TGltaXRzIjp7InJlYWRCYXRjaFNpemUiOjUwLCJyZWFkVGltZW91dCI6IjFzIiwiYnVmZmVyTWF4TGVuZ3RoIjozMDAwMCwiYnVmZmVyVXNhZ2VMaW1pdCI6ODB9LCJ0b1ZlcnRleFR5cGUiOiJTaW5rIiwidG9WZXJ0ZXhQYXJ0aXRpb25Db3VudCI6MSwidG9WZXJ0ZXhMaW1pdHMiOnsicmVhZEJhdGNoU2l6ZSI6NTAsInJlYWRUaW1lb3V0IjoiMXMiLCJidWZmZXJNYXhMZW5ndGgiOjMwMDAwLCJidWZmZXJVc2FnZUxpbWl0Ijo4MH19XSwid2F0ZXJtYXJrIjp7Im1heERlbGF5IjoiMHMifX0sInN0YXR1cyI6eyJwaGFzZSI6IiIsInJlcGxpY2FzIjowLCJkZXNpcmVkUmVwbGljYXMiOjAsImxhc3RTY2FsZWRBdCI6bnVsbH19"; + + let env_vars = [("NUMAFLOW_ISBSVC_JETSTREAM_URL", "localhost:4222")]; + let pipeline_config = + PipelineConfig::load(pipeline_cfg_base64.to_string(), env_vars).unwrap(); + + let expected = PipelineConfig { + pipeline_name: "simple-pipeline".to_string(), + vertex_name: "in".to_string(), + replica: 0, + batch_size: 50, + paf_batch_size: 30000, + read_timeout: Duration::from_secs(1), + js_client_config: isb::jetstream::ClientConfig { + url: "localhost:4222".to_string(), + user: None, + password: None, + }, + from_vertex_config: vec![], + to_vertex_config: vec![ToVertexConfig { + name: "out".to_string(), + writer_config: BufferWriterConfig { + streams: vec![("default-simple-pipeline-out-0".to_string(), 0)], + partitions: 1, + max_length: 30000, + usage_limit: 0.8, + ..Default::default() + }, + partitions: 1, + conditions: None, + }], + vertex_config: VertexType::Source(SourceVtxConfig { + source_config: SourceConfig { + source_type: SourceType::Pulsar(PulsarSourceConfig { + pulsar_server_addr: "pulsar://pulsar-service:6650".to_string(), + topic: "test_persistent".to_string(), + consumer_name: "my_persistent_consumer".to_string(), + subscription: "my_persistent_subscription".to_string(), + max_unack: 1000, + auth: None, + }), + }, + transformer_config: None, + }), + metrics_config: Default::default(), + }; + + assert_eq!(pipeline_config, expected); + } } diff --git a/rust/numaflow-core/src/error.rs b/rust/numaflow-core/src/error.rs index b64896f26b..27cbcb6fc9 100644 --- a/rust/numaflow-core/src/error.rs +++ b/rust/numaflow-core/src/error.rs @@ -40,6 +40,15 @@ pub enum Error { #[error("OneShot Receiver Error - {0}")] ActorPatternRecv(String), + + #[error("Ack Pending Exceeded, pending={0}")] + AckPendingExceeded(usize), + + #[error("Offset (id={0}) not found to Ack")] + AckOffsetNotFound(String), + + #[error("Lag cannot be fetched, {0}")] + Lag(String), } impl From for Error { diff --git a/rust/numaflow-core/src/message.rs b/rust/numaflow-core/src/message.rs index f24212967f..3d8407ec59 100644 --- a/rust/numaflow-core/src/message.rs +++ b/rust/numaflow-core/src/message.rs @@ -122,8 +122,8 @@ impl TryFrom for Message { /// IntOffset is integer based offset enum type. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct IntOffset { - offset: u64, - partition_idx: u16, + pub(crate) offset: u64, + pub(crate) partition_idx: u16, } impl IntOffset { diff --git a/rust/numaflow-core/src/monovertex.rs b/rust/numaflow-core/src/monovertex.rs index 185c96bfe9..8e6d9cad19 100644 --- a/rust/numaflow-core/src/monovertex.rs +++ b/rust/numaflow-core/src/monovertex.rs @@ -18,6 +18,7 @@ use crate::shared::utils::{ }; use crate::sink::{SinkClientType, SinkHandle}; use crate::source::generator::new_generator; +use crate::source::pulsar::new_pulsar_source; use crate::source::user_defined::new_source; use crate::source::{SourceHandle, SourceType}; use crate::transformer::user_defined::SourceTransformHandle; @@ -219,25 +220,35 @@ async fn fetch_source( config: &MonovertexConfig, source_grpc_client: &mut Option>, ) -> crate::Result { - // check whether the source grpc client is provided, this happens only of the source is a - // user defined source - if let Some(source_grpc_client) = source_grpc_client.clone() { - let (source_read, source_ack, lag_reader) = - new_source(source_grpc_client, config.batch_size, config.read_timeout).await?; - return Ok(SourceType::UserDefinedSource( - source_read, - source_ack, - lag_reader, - )); - } - - // now that we know it is not a user-defined source, it has to be a built-in - if let source::SourceType::Generator(generator_config) = &config.source_config.source_type { - let (source_read, source_ack, lag_reader) = - new_generator(generator_config.clone(), config.batch_size)?; - Ok(SourceType::Generator(source_read, source_ack, lag_reader)) - } else { - Err(Error::Config("No valid source configuration found".into())) + match &config.source_config.source_type { + source::SourceType::Generator(generator_config) => { + let (source_read, source_ack, lag_reader) = + new_generator(generator_config.clone(), config.batch_size)?; + Ok(SourceType::Generator(source_read, source_ack, lag_reader)) + } + source::SourceType::UserDefined(_) => { + let Some(source_grpc_client) = source_grpc_client.clone() else { + return Err(Error::Config( + "Configuration type is user-defined, however no grpc client is provided".into(), + )); + }; + let (source_read, source_ack, lag_reader) = + new_source(source_grpc_client, config.batch_size, config.read_timeout).await?; + Ok(SourceType::UserDefinedSource( + source_read, + source_ack, + lag_reader, + )) + } + source::SourceType::Pulsar(pulsar_config) => { + let pulsar = new_pulsar_source( + pulsar_config.clone(), + config.batch_size, + config.read_timeout, + ) + .await?; + Ok(SourceType::Pulsar(pulsar)) + } } } diff --git a/rust/numaflow-core/src/pipeline.rs b/rust/numaflow-core/src/pipeline.rs index 52719c8827..ef49bdc759 100644 --- a/rust/numaflow-core/src/pipeline.rs +++ b/rust/numaflow-core/src/pipeline.rs @@ -1,14 +1,3 @@ -use async_nats::jetstream::Context; -use async_nats::{jetstream, ConnectOptions}; -use futures::future::try_join_all; -use numaflow_pb::clients::sink::sink_client::SinkClient; -use numaflow_pb::clients::source::source_client::SourceClient; -use numaflow_pb::clients::sourcetransformer::source_transform_client::SourceTransformClient; -use std::collections::HashMap; -use std::time::Duration; -use tokio_util::sync::CancellationToken; -use tonic::transport::Channel; - use crate::config::components::source::SourceType; use crate::config::pipeline; use crate::config::pipeline::PipelineConfig; @@ -22,9 +11,20 @@ use crate::shared::utils::{ }; use crate::sink::SinkWriter; use crate::source::generator::new_generator; +use crate::source::pulsar::new_pulsar_source; use crate::source::user_defined::new_source; use crate::transformer::user_defined::SourceTransformHandle; use crate::{config, error, source, Result}; +use async_nats::jetstream::Context; +use async_nats::{jetstream, ConnectOptions}; +use futures::future::try_join_all; +use numaflow_pb::clients::sink::sink_client::SinkClient; +use numaflow_pb::clients::source::source_client::SourceClient; +use numaflow_pb::clients::sourcetransformer::source_transform_client::SourceTransformClient; +use std::collections::HashMap; +use std::time::Duration; +use tokio_util::sync::CancellationToken; +use tonic::transport::Channel; mod forwarder; mod isb; @@ -256,6 +256,15 @@ async fn create_source_type( Some(source_grpc_client), )) } + SourceType::Pulsar(pulsar_config) => { + let pulsar_source = new_pulsar_source( + pulsar_config.clone(), + config.batch_size, + config.read_timeout, + ) + .await?; + Ok((source::SourceType::Pulsar(pulsar_source), None)) + } } } /// Creates a transformer if it is configured in the pipeline @@ -296,7 +305,6 @@ async fn create_js_context(config: pipeline::isb::jetstream::ClientConfig) -> Re .max_reconnects(None) // -1 for unlimited reconnects .ping_interval(Duration::from_secs(3)) .max_reconnects(None) - .ping_interval(Duration::from_secs(3)) .retry_on_initial_connect(); if let (Some(user), Some(password)) = (config.user, config.password) { diff --git a/rust/numaflow-core/src/shared/utils.rs b/rust/numaflow-core/src/shared/utils.rs index a6cea7eaed..c035c67fce 100644 --- a/rust/numaflow-core/src/shared/utils.rs +++ b/rust/numaflow-core/src/shared/utils.rs @@ -207,6 +207,15 @@ pub(crate) async fn create_sink_handle( } } +// Retrieve value from mounted secret volume +// "/var/numaflow/secrets/${secretRef.name}/${secretRef.key}" is expected to be the file path +pub(crate) fn get_secret_from_volume(name: &str, key: &str) -> std::result::Result { + let path = format!("/var/numaflow/secrets/{name}/{key}"); + let val = std::fs::read_to_string(path.clone()) + .map_err(|e| format!("Reading secret from file {path}: {e:?}"))?; + Ok(val.trim().into()) +} + #[cfg(test)] mod tests { use numaflow::source::{Message, Offset, SourceReadRequest}; diff --git a/rust/numaflow-core/src/source.rs b/rust/numaflow-core/src/source.rs index 2c7bc0b83c..f851268b72 100644 --- a/rust/numaflow-core/src/source.rs +++ b/rust/numaflow-core/src/source.rs @@ -1,9 +1,9 @@ -use tokio::sync::{mpsc, oneshot}; - use crate::{ message::{Message, Offset}, reader::LagReader, }; +use numaflow_pulsar::source::PulsarSource; +use tokio::sync::{mpsc, oneshot}; /// [User-Defined Source] extends Numaflow to add custom sources supported outside the builtins. /// @@ -15,6 +15,11 @@ pub(crate) mod user_defined; /// [Generator]: https://numaflow.numaproj.io/user-guide/sources/generator/ pub(crate) mod generator; +/// [Pulsar] is a builtin to ingest data from a Pulsar topic +/// +/// [Pulsar]: https://numaflow.numaproj.io/user-guide/sources/pulsar/ +pub(crate) mod pulsar; + /// Set of Read related items that has to be implemented to become a Source. pub(crate) trait SourceReader { #[allow(dead_code)] @@ -123,6 +128,19 @@ impl SourceHandle { } }); } + SourceType::Pulsar(pulsar_source) => { + tokio::spawn(async move { + let mut actor = SourceActor::new( + receiver, + pulsar_source.clone(), + pulsar_source.clone(), + pulsar_source, + ); + while let Some(msg) = actor.receiver.recv().await { + actor.handle_message(msg).await; + } + }); + } }; Self { sender } } @@ -175,4 +193,5 @@ pub(crate) enum SourceType { generator::GeneratorAck, generator::GeneratorLagReader, ), + Pulsar(PulsarSource), } diff --git a/rust/numaflow-core/src/source/pulsar.rs b/rust/numaflow-core/src/source/pulsar.rs new file mode 100644 index 0000000000..6d8d1d33f3 --- /dev/null +++ b/rust/numaflow-core/src/source/pulsar.rs @@ -0,0 +1,157 @@ +use std::time::Duration; + +use crate::error::Error; +use crate::message::{get_vertex_name, IntOffset, Message, MessageID, Offset}; +use crate::source; +use numaflow_pulsar::source::{PulsarMessage, PulsarSource, PulsarSourceConfig}; + +impl TryFrom for Message { + type Error = Error; + + fn try_from(message: PulsarMessage) -> crate::Result { + let offset = Offset::Int(IntOffset::new(message.offset, 1)); // FIXME: partition id + + Ok(Message { + keys: vec![message.key], + value: message.payload, + offset: Some(offset.clone()), + event_time: message.event_time, + id: MessageID { + vertex_name: get_vertex_name().to_string(), + offset: offset.to_string(), + index: 0, + }, + headers: message.headers, + }) + } +} + +impl From for Error { + fn from(value: numaflow_pulsar::Error) -> Self { + match value { + numaflow_pulsar::Error::Pulsar(e) => Error::Source(e.to_string()), + numaflow_pulsar::Error::UnknownOffset(_) => Error::Source(value.to_string()), + numaflow_pulsar::Error::AckPendingExceeded(pending) => { + Error::AckPendingExceeded(pending) + } + numaflow_pulsar::Error::ActorTaskTerminated(_) => { + Error::ActorPatternRecv(value.to_string()) + } + numaflow_pulsar::Error::Other(e) => Error::Source(e), + } + } +} + +pub(crate) async fn new_pulsar_source( + cfg: PulsarSourceConfig, + batch_size: usize, + timeout: Duration, +) -> crate::Result { + Ok(PulsarSource::new(cfg, batch_size, timeout).await?) +} + +impl source::SourceReader for PulsarSource { + fn name(&self) -> &'static str { + "Pulsar" + } + + async fn read(&mut self) -> crate::Result> { + self.read_messages() + .await? + .into_iter() + .map(|msg| msg.try_into()) + .collect() + } + + fn partitions(&self) -> Vec { + Self::partitions(self) + } +} + +impl source::SourceAcker for PulsarSource { + async fn ack(&mut self, offsets: Vec) -> crate::error::Result<()> { + let mut pulsar_offsets = Vec::with_capacity(offsets.len()); + for offset in offsets { + let Offset::Int(int_offset) = offset else { + return Err(Error::Source(format!( + "Expected Offset::Int type for Pulsar. offset={offset:?}" + ))); + }; + pulsar_offsets.push(int_offset.offset); + } + self.ack_offsets(pulsar_offsets).await.map_err(Into::into) + } +} + +impl source::LagReader for PulsarSource { + async fn pending(&mut self) -> crate::error::Result> { + Ok(self.pending_count().await) + } +} + +#[cfg(feature = "pulsar-tests")] +#[cfg(test)] +mod tests { + use pulsar::{producer, proto, Pulsar, TokioExecutor}; + use source::{LagReader, SourceAcker, SourceReader}; + + use super::*; + + type Result = std::result::Result>; + + #[tokio::test] + async fn test_pulsar_source() -> Result<()> { + let cfg = PulsarSourceConfig { + pulsar_server_addr: "pulsar://localhost:6650".into(), + topic: "persistent://public/default/test_persistent".into(), + consumer_name: "test".into(), + subscription: "test".into(), + max_unack: 100, + auth: None, + }; + let mut pulsar = new_pulsar_source(cfg, 10, Duration::from_millis(200)).await?; + assert_eq!(pulsar.name(), "Pulsar"); + + // Read should return before the timeout + let msgs = tokio::time::timeout(Duration::from_millis(400), pulsar.read_messages()).await; + assert!(msgs.is_ok()); + + assert!(pulsar.pending().await.unwrap().is_none()); + + let pulsar_producer: Pulsar<_> = Pulsar::builder("pulsar://localhost:6650", TokioExecutor) + .build() + .await + .unwrap(); + let mut pulsar_producer = pulsar_producer + .producer() + .with_topic("persistent://public/default/test_persistent") + .with_name("my producer") + .with_options(producer::ProducerOptions { + schema: Some(proto::Schema { + r#type: proto::schema::Type::String as i32, + ..Default::default() + }), + ..Default::default() + }) + .build() + .await + .unwrap(); + + let data: Vec = (0..10).map(|i| format!("test_data_{i}")).collect(); + let send_futures = pulsar_producer + .send_all(data) + .await + .map_err(|e| format!("Sending messages to Pulsar: {e:?}"))?; + for fut in send_futures { + fut.await?; + } + + let messages = pulsar.read().await?; + assert_eq!(messages.len(), 10); + + let offsets: Vec = messages.into_iter().map(|m| m.offset.unwrap()).collect(); + pulsar.ack(offsets).await?; + + Ok(()) + } +} diff --git a/rust/numaflow-extns/pulsar/Cargo.toml b/rust/numaflow-extns/pulsar/Cargo.toml new file mode 100644 index 0000000000..cc91a495df --- /dev/null +++ b/rust/numaflow-extns/pulsar/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "numaflow-pulsar" +version = "0.1.0" +edition = "2021" + +[lints.rust] +unsafe_code = "forbid" +unused_must_use = "forbid" + +[lints.clippy] +enum_glob_use = "deny" + +[dependencies] +prost = "0.11.9" +tokio = "1.41.1" +tonic = "0.12.3" +serde = { version = "1.0.204", features = ["derive"] } +tracing = "0.1.40" +bincode = "1.3.3" +chrono = "0.4.38" +# Rustls doesn't allow accepting self-signed certs: https://github.com/streamnative/pulsar-rs/blob/715411cb365932c379d4b5d0a8fde2ac46c54055/src/connection.rs#L912 +pulsar = {version = "6.3.0", default-features = false, features = ["tokio-rustls-runtime"]} +bytes = "1.7.1" +thiserror = "2.0.3" diff --git a/rust/numaflow-extns/pulsar/src/lib.rs b/rust/numaflow-extns/pulsar/src/lib.rs new file mode 100644 index 0000000000..f6e8306a4e --- /dev/null +++ b/rust/numaflow-extns/pulsar/src/lib.rs @@ -0,0 +1,35 @@ +use tokio::sync::oneshot; + +pub mod source; + +pub type Result = core::result::Result; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("metrics Error - {0}")] + Pulsar(pulsar::Error), + + #[error("Messages to be acknowledged has reached its configured limit. Pending={0}")] + AckPendingExceeded(usize), + + #[error("Failed to receive message from channel. Actor task is terminated: {0:?}")] + ActorTaskTerminated(oneshot::error::RecvError), + + #[error("Received unknown offset for acknowledgement. offset={0}")] + UnknownOffset(u64), + + #[error("{0}")] + Other(String), +} + +impl From for Error { + fn from(value: pulsar::Error) -> Self { + Error::Pulsar(value) + } +} + +impl From for Error { + fn from(value: String) -> Self { + Error::Other(value) + } +} diff --git a/rust/numaflow-extns/pulsar/src/source.rs b/rust/numaflow-extns/pulsar/src/source.rs new file mode 100644 index 0000000000..7d2c13ed1d --- /dev/null +++ b/rust/numaflow-extns/pulsar/src/source.rs @@ -0,0 +1,298 @@ +use std::collections::BTreeMap; +use std::{collections::HashMap, time::Duration}; + +use bytes::Bytes; +use chrono::{DateTime, Utc}; +use pulsar::Authentication; +use pulsar::{proto::MessageIdData, Consumer, ConsumerOptions, Pulsar, SubType, TokioExecutor}; +use tokio::time::Instant; +use tokio::{ + sync::{mpsc, oneshot}, + time, +}; +use tonic::codegen::tokio_stream::StreamExt; + +use crate::{Error, Result}; + +#[derive(Debug, Clone, PartialEq)] +pub struct PulsarSourceConfig { + pub pulsar_server_addr: String, + pub topic: String, + pub consumer_name: String, + pub subscription: String, + pub max_unack: usize, + pub auth: Option, +} + +#[derive(Clone, PartialEq)] +pub enum PulsarAuth { + JWT(String), +} + +impl std::fmt::Debug for PulsarAuth { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PulsarAuth::JWT(token) => { + write!(f, "{}****{}", &token[..6], &token[token.len() - 6..]) + } + } + } +} + +enum ConsumerActorMessage { + Read { + count: usize, + timeout_at: Instant, + respond_to: oneshot::Sender>>, + }, + Ack { + offsets: Vec, + respond_to: oneshot::Sender>, + }, +} + +pub struct PulsarMessage { + pub key: String, + pub payload: Bytes, + pub offset: u64, + pub event_time: DateTime, + pub headers: HashMap, +} + +struct ConsumerReaderActor { + consumer: Consumer, TokioExecutor>, + handler_rx: mpsc::Receiver, + message_ids: BTreeMap, + max_unack: usize, + topic: String, +} + +impl ConsumerReaderActor { + async fn start( + config: PulsarSourceConfig, + handler_rx: mpsc::Receiver, + ) -> Result<()> { + tracing::info!( + addr = &config.pulsar_server_addr, + "Pulsar connection details" + ); + + // Rustls doesn't allow accepting self-signed certs: https://github.com/streamnative/pulsar-rs/blob/715411cb365932c379d4b5d0a8fde2ac46c54055/src/connection.rs#L912 + // The `with_allow_insecure_connection()` option has no effect + let mut pulsar = Pulsar::builder(&config.pulsar_server_addr, TokioExecutor); + if let Some(PulsarAuth::JWT(token)) = config.auth { + let auth_token = Authentication { + name: "token".into(), + data: token.into(), + }; + pulsar = pulsar.with_auth(auth_token); + } + + let pulsar: Pulsar<_> = pulsar + .build() + .await + .map_err(|e| format!("Creating Pulsar client connection: {e:?}"))?; + + let consumer: Consumer, TokioExecutor> = pulsar + .consumer() + .with_topic(&config.topic) + .with_consumer_name(&config.consumer_name) + .with_subscription_type(SubType::Shared) + .with_subscription(&config.subscription) + .with_options(ConsumerOptions::default().durable(true)) + .build() + .await + .map_err(|e| format!("Creating a Pulsar consumer: {e:?}"))?; + + tokio::spawn(async move { + let mut consumer_actor = ConsumerReaderActor { + consumer, + handler_rx, + message_ids: BTreeMap::new(), + max_unack: config.max_unack, + topic: config.topic, + }; + consumer_actor.run().await; + }); + Ok(()) + } + + async fn run(&mut self) { + while let Some(msg) = self.handler_rx.recv().await { + self.handle_message(msg).await; + } + } + + async fn handle_message(&mut self, msg: ConsumerActorMessage) { + match msg { + ConsumerActorMessage::Read { + count, + timeout_at, + respond_to, + } => { + let messages = self.get_messages(count, timeout_at).await; + let _ = respond_to.send(messages); + } + ConsumerActorMessage::Ack { + offsets, + respond_to, + } => { + let status = self.ack_messages(offsets).await; + let _ = respond_to.send(status); + } + } + } + + async fn get_messages( + &mut self, + count: usize, + timeout_at: Instant, + ) -> Result> { + if self.message_ids.len() >= self.max_unack { + return Err(Error::AckPendingExceeded(self.message_ids.len())); + } + let mut messages = vec![]; + for _ in 0..count { + let remaining_time = timeout_at - Instant::now(); + let Ok(msg) = time::timeout(remaining_time, self.consumer.try_next()).await else { + return Ok(messages); + }; + let msg = match msg { + Ok(Some(msg)) => msg, + Ok(None) => break, + Err(e) => { + tracing::error!(?e, "Fetching message from Pulsar"); + let remaining_time = timeout_at - Instant::now(); + if remaining_time.as_millis() >= 100 { + time::sleep(Duration::from_millis(50)).await; // FIXME: add error metrics. Also, respect the timeout + continue; + } + return Err(Error::Pulsar(e)); + } + }; + let offset = msg.message_id().entry_id; + let event_time = msg + .metadata() + .event_time + .unwrap_or(msg.metadata().publish_time); + let Some(event_time) = chrono::DateTime::from_timestamp_millis(event_time as i64) + else { + // This should never happen + tracing::error!( + event_time = msg.metadata().event_time, + publish_time = msg.metadata().publish_time, + parsed_event_time = event_time, + "Pulsar message contains invalid event_time/publish_time timestamp" + ); + continue; + //FIXME: NACK the message + }; + + self.message_ids.insert(offset, msg.message_id().clone()); + let headers = msg + .metadata() + .properties + .iter() + .map(|prop| (prop.key.clone(), prop.value.clone())) + .collect(); + + messages.push(PulsarMessage { + key: msg.key().unwrap_or_else(|| "".to_string()), // FIXME: This is partition key. Identify the correct option. Also, there is a partition_key_b64_encoded boolean option in Pulsar metadata + payload: msg.payload.data.into(), + offset, + event_time, + headers, + }); + + // stop reading as soon as we hit max_unack + if messages.len() >= self.max_unack { + return Ok(messages); + } + } + Ok(messages) + } + + // TODO: Identify the longest continuous batch and use cumulative_ack_with_id() to ack them all. + async fn ack_messages(&mut self, offsets: Vec) -> Result<()> { + for offset in offsets { + let msg_id = self.message_ids.remove(&offset); + + let Some(msg_id) = msg_id else { + return Err(Error::UnknownOffset(offset)); + }; + + let Err(e) = self.consumer.ack_with_id(&self.topic, msg_id.clone()).await else { + continue; + }; + // Insert offset back + self.message_ids.insert(offset, msg_id); + return Err(Error::Pulsar(e.into())); + } + Ok(()) + } +} + +#[derive(Clone)] +pub struct PulsarSource { + batch_size: usize, + /// timeout for each batch read request + timeout: Duration, + actor_tx: mpsc::Sender, +} + +impl PulsarSource { + pub async fn new( + config: PulsarSourceConfig, + batch_size: usize, + timeout: Duration, + ) -> Result { + let (tx, rx) = mpsc::channel(10); + ConsumerReaderActor::start(config, rx).await?; + Ok(Self { + actor_tx: tx, + batch_size, + timeout, + }) + } +} + +impl PulsarSource { + pub async fn read_messages(&self) -> Result> { + let start = Instant::now(); + let (tx, rx) = oneshot::channel(); + let msg = ConsumerActorMessage::Read { + count: self.batch_size, + timeout_at: Instant::now() + self.timeout, + respond_to: tx, + }; + let _ = self.actor_tx.send(msg).await; + let messages = rx.await.map_err(Error::ActorTaskTerminated)??; + tracing::debug!( + count = messages.len(), + requested_count = self.batch_size, + time_taken_ms = start.elapsed().as_millis(), + "Got messages from pulsar" + ); + Ok(messages) + } + + pub async fn ack_offsets(&self, offsets: Vec) -> Result<()> { + let (tx, rx) = oneshot::channel(); + let _ = self + .actor_tx + .send(ConsumerActorMessage::Ack { + offsets, + respond_to: tx, + }) + .await; + rx.await.map_err(Error::ActorTaskTerminated)? + } + + pub async fn pending_count(&self) -> Option { + None + } + + pub fn partitions(&self) -> Vec { + todo!() + } +} diff --git a/rust/numaflow-models/src/models/mod.rs b/rust/numaflow-models/src/models/mod.rs index bfbcd121d0..7d890089a8 100644 --- a/rust/numaflow-models/src/models/mod.rs +++ b/rust/numaflow-models/src/models/mod.rs @@ -124,6 +124,10 @@ pub mod pipeline_status; pub use self::pipeline_status::PipelineStatus; pub mod probe; pub use self::probe::Probe; +pub mod pulsar_auth; +pub use self::pulsar_auth::PulsarAuth; +pub mod pulsar_source; +pub use self::pulsar_source::PulsarSource; pub mod redis_buffer_service; pub use self::redis_buffer_service::RedisBufferService; pub mod redis_config; diff --git a/rust/numaflow-models/src/models/pulsar_auth.rs b/rust/numaflow-models/src/models/pulsar_auth.rs new file mode 100644 index 0000000000..7b5299157d --- /dev/null +++ b/rust/numaflow-models/src/models/pulsar_auth.rs @@ -0,0 +1,32 @@ +/* +Copyright 2022 The Numaproj Authors. + +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. +*/ + +// Code generated by Openapi Generator. DO NOT EDIT. + +/// PulsarAuth : PulsarAuth defines how to authenticate with Pulsar + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct PulsarAuth { + #[serde(rename = "token", skip_serializing_if = "Option::is_none")] + pub token: Option, +} + +impl PulsarAuth { + /// PulsarAuth defines how to authenticate with Pulsar + pub fn new() -> PulsarAuth { + PulsarAuth { token: None } + } +} diff --git a/rust/numaflow-models/src/models/pulsar_source.rs b/rust/numaflow-models/src/models/pulsar_source.rs new file mode 100644 index 0000000000..3324ebf12b --- /dev/null +++ b/rust/numaflow-models/src/models/pulsar_source.rs @@ -0,0 +1,52 @@ +/* +Copyright 2022 The Numaproj Authors. + +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. +*/ + +// Code generated by Openapi Generator. DO NOT EDIT. + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct PulsarSource { + #[serde(rename = "auth", skip_serializing_if = "Option::is_none")] + pub auth: Option>, + #[serde(rename = "consumerName")] + pub consumer_name: String, + /// Maximum number of messages that are in not yet acked state. Once this limit is crossed, futher read requests will return empty list. + #[serde(rename = "maxUnack", skip_serializing_if = "Option::is_none")] + pub max_unack: Option, + #[serde(rename = "serverAddr")] + pub server_addr: String, + #[serde(rename = "subscriptionName")] + pub subscription_name: String, + #[serde(rename = "topic")] + pub topic: String, +} + +impl PulsarSource { + pub fn new( + consumer_name: String, + server_addr: String, + subscription_name: String, + topic: String, + ) -> PulsarSource { + PulsarSource { + auth: None, + consumer_name, + max_unack: None, + server_addr, + subscription_name, + topic, + } + } +} diff --git a/rust/numaflow-models/src/models/source.rs b/rust/numaflow-models/src/models/source.rs index a5569b86fa..f5ede490e2 100644 --- a/rust/numaflow-models/src/models/source.rs +++ b/rust/numaflow-models/src/models/source.rs @@ -28,6 +28,8 @@ pub struct Source { pub kafka: Option>, #[serde(rename = "nats", skip_serializing_if = "Option::is_none")] pub nats: Option>, + #[serde(rename = "pulsar", skip_serializing_if = "Option::is_none")] + pub pulsar: Option>, #[serde(rename = "serving", skip_serializing_if = "Option::is_none")] pub serving: Option>, #[serde(rename = "transformer", skip_serializing_if = "Option::is_none")] @@ -44,6 +46,7 @@ impl Source { jetstream: None, kafka: None, nats: None, + pulsar: None, serving: None, transformer: None, udsource: None, diff --git a/rust/rust-toolchain.toml b/rust/rust-toolchain.toml index d298aadb69..06bea96e8f 100644 --- a/rust/rust-toolchain.toml +++ b/rust/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] profile = "default" -channel = "1.81" +channel = "1.82"