| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you 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. |
| |
| use std::{error::Error as _, fmt}; |
| |
| use crate::{ |
| schema::{Name, RecordSchema, Schema, SchemaKind, UnionSchema}, |
| types::{Value, ValueKind}, |
| }; |
| |
| /// Errors encountered by Avro. |
| /// |
| /// To inspect the details of the error use [`details`](Self::details) or [`into_details`](Self::into_details) |
| /// to get a [`Details`] which contains more precise error information. |
| /// |
| /// See [`Details`] for all possible errors. |
| #[derive(thiserror::Error, Debug)] |
| #[repr(transparent)] |
| #[error(transparent)] |
| pub struct Error { |
| details: Box<Details>, |
| } |
| |
| impl Error { |
| pub fn new(details: Details) -> Self { |
| Self { |
| details: Box::new(details), |
| } |
| } |
| |
| pub fn details(&self) -> &Details { |
| &self.details |
| } |
| |
| pub fn into_details(self) -> Details { |
| *self.details |
| } |
| } |
| |
| impl From<Details> for Error { |
| fn from(details: Details) -> Self { |
| Self::new(details) |
| } |
| } |
| |
| impl serde::ser::Error for Error { |
| fn custom<T: fmt::Display>(msg: T) -> Self { |
| Self::new(<Details as serde::ser::Error>::custom(msg)) |
| } |
| } |
| |
| impl serde::de::Error for Error { |
| fn custom<T: fmt::Display>(msg: T) -> Self { |
| Self::new(<Details as serde::de::Error>::custom(msg)) |
| } |
| } |
| |
| #[derive(thiserror::Error)] |
| pub enum Details { |
| #[error("Bad Snappy CRC32; expected {expected:x} but got {actual:x}")] |
| SnappyCrc32 { expected: u32, actual: u32 }, |
| |
| #[error("Invalid u8 for bool: {0}")] |
| BoolValue(u8), |
| |
| #[error("Not a fixed value, required for decimal with fixed schema: {0:?}")] |
| FixedValue(Value), |
| |
| #[error("Not a bytes value, required for decimal with bytes schema: {0:?}")] |
| BytesValue(Value), |
| |
| #[error("Not a string value, required for uuid: {0:?}")] |
| GetUuidFromStringValue(Value), |
| |
| #[error("Two schemas with the same fullname were given: {0:?}")] |
| NameCollision(String), |
| |
| #[error("Not a fixed or bytes type, required for decimal schema, got: {0:?}")] |
| ResolveDecimalSchema(SchemaKind), |
| |
| #[error("Invalid utf-8 string")] |
| ConvertToUtf8(#[source] std::string::FromUtf8Error), |
| |
| #[error("Invalid utf-8 string")] |
| ConvertToUtf8Error(#[source] std::str::Utf8Error), |
| |
| /// Describes errors happened while validating Avro data. |
| #[error("Value does not match schema")] |
| Validation, |
| |
| /// Describes errors happened while validating Avro data. |
| #[error("Value {value:?} does not match schema {schema:?}: Reason: {reason}")] |
| ValidationWithReason { |
| value: Value, |
| schema: Schema, |
| reason: String, |
| }, |
| |
| #[error( |
| "Unable to allocate {desired} bytes (maximum allowed: {maximum}). Change the limit using `apache_avro::util::max_allocation_bytes`" |
| )] |
| MemoryAllocation { desired: usize, maximum: usize }, |
| |
| /// Describe a specific error happening with decimal representation |
| #[error( |
| "Number of bytes requested for decimal sign extension {requested} is less than the number of bytes needed to decode {needed}" |
| )] |
| SignExtend { requested: usize, needed: usize }, |
| |
| #[error("Failed to read boolean bytes: {0}")] |
| ReadBoolean(#[source] std::io::Error), |
| |
| #[error("Failed to read bytes: {0}")] |
| ReadBytes(#[source] std::io::Error), |
| |
| #[error("Failed to read string: {0}")] |
| ReadString(#[source] std::io::Error), |
| |
| #[error("Failed to read double: {0}")] |
| ReadDouble(#[source] std::io::Error), |
| |
| #[error("Failed to read float: {0}")] |
| ReadFloat(#[source] std::io::Error), |
| |
| #[error("Failed to read duration: {0}")] |
| ReadDuration(#[source] std::io::Error), |
| |
| #[error("Failed to read fixed number of bytes '{1}': : {0}")] |
| ReadFixed(#[source] std::io::Error, usize), |
| |
| #[error("Failed to convert &str to UUID: {0}")] |
| ConvertStrToUuid(#[source] uuid::Error), |
| |
| #[error("Failed to convert Fixed bytes to UUID. It must be exactly 16 bytes, got {0}")] |
| ConvertFixedToUuid(usize), |
| |
| #[error("Failed to convert Fixed bytes to UUID: {0}")] |
| ConvertSliceToUuid(#[source] uuid::Error), |
| |
| #[error("Map key is not a string; key type is {0:?}")] |
| MapKeyType(ValueKind), |
| |
| #[error("Union index {index} out of bounds: {num_variants}")] |
| GetUnionVariant { index: i64, num_variants: usize }, |
| |
| #[error( |
| "Enum symbol index out of bounds: got {index} but there are only {num_variants} variants" |
| )] |
| EnumSymbolIndex { index: usize, num_variants: usize }, |
| |
| #[error("Enum symbol not found {0}")] |
| GetEnumSymbol(String), |
| |
| #[error("Unable to decode enum index")] |
| GetEnumUnknownIndexValue, |
| |
| #[error("Scale {scale} is greater than precision {precision}")] |
| GetScaleAndPrecision { scale: usize, precision: usize }, |
| |
| #[error( |
| "Fixed type number of bytes {size} is not large enough to hold decimal values of precision {precision}" |
| )] |
| GetScaleWithFixedSize { size: usize, precision: usize }, |
| |
| #[error("Expected Value::Uuid, got: {0:?}")] |
| GetUuid(Value), |
| |
| #[error("Expected Value::BigDecimal, got: {0:?}")] |
| GetBigDecimal(Value), |
| |
| #[error("Fixed bytes of size 12 expected, got Fixed of size {0}")] |
| GetDurationFixedBytes(usize), |
| |
| #[error("Expected Value::Duration or Value::Fixed(12), got: {0:?}")] |
| ResolveDuration(Value), |
| |
| #[error("Expected Value::Decimal, Value::Bytes, Value::Fixed or Value::String, got: {0:?}")] |
| ResolveDecimal(Value), |
| |
| #[error("Missing field in record: {0:?}")] |
| GetField(String), |
| |
| #[error("Unable to convert to u8, got {0:?}")] |
| GetU8(Value), |
| |
| #[error("Precision {precision} too small to hold decimal values with {num_bytes} bytes")] |
| ComparePrecisionAndSize { precision: usize, num_bytes: usize }, |
| |
| #[error("Cannot convert length to i32: {1}")] |
| ConvertLengthToI32(#[source] std::num::TryFromIntError, usize), |
| |
| #[error("Expected Value::Date or Value::Int, got: {0:?}")] |
| GetDate(Value), |
| |
| #[error("Expected Value::TimeMillis or Value::Int, got: {0:?}")] |
| GetTimeMillis(Value), |
| |
| #[error("Expected Value::TimeMicros, Value::Long or Value::Int, got: {0:?}")] |
| GetTimeMicros(Value), |
| |
| #[error("Expected Value::TimestampMillis, Value::Long or Value::Int, got: {0:?}")] |
| GetTimestampMillis(Value), |
| |
| #[error("Expected Value::TimestampMicros, Value::Long or Value::Int, got: {0:?}")] |
| GetTimestampMicros(Value), |
| |
| #[error("Expected Value::TimestampNanos, Value::Long or Value::Int, got: {0:?}")] |
| GetTimestampNanos(Value), |
| |
| #[error("Expected Value::LocalTimestampMillis, Value::Long or Value::Int, got: {0:?}")] |
| GetLocalTimestampMillis(Value), |
| |
| #[error("Expected Value::LocalTimestampMicros, Value::Long or Value::Int, got: {0:?}")] |
| GetLocalTimestampMicros(Value), |
| |
| #[error("Expected Value::LocalTimestampNanos, Value::Long or Value::Int, got: {0:?}")] |
| GetLocalTimestampNanos(Value), |
| |
| #[error("Expected Value::Null, got: {0:?}")] |
| GetNull(Value), |
| |
| #[error("Expected Value::Boolean, got: {0:?}")] |
| GetBoolean(Value), |
| |
| #[error("Expected Value::Int, got: {0:?}")] |
| GetInt(Value), |
| |
| #[error("Expected Value::Long or Value::Int, got: {0:?}")] |
| GetLong(Value), |
| |
| #[error(r#"Expected Value::Double, Value::Float, Value::Int, Value::Long or Value::String ("NaN", "INF", "Infinity", "-INF" or "-Infinity"), got: {0:?}"#)] |
| GetDouble(Value), |
| |
| #[error(r#"Expected Value::Float, Value::Double, Value::Int, Value::Long or Value::String ("NaN", "INF", "Infinity", "-INF" or "-Infinity"), got: {0:?}"#)] |
| GetFloat(Value), |
| |
| #[error("Expected Value::Bytes, got: {0:?}")] |
| GetBytes(Value), |
| |
| #[error("Expected Value::String, Value::Bytes or Value::Fixed, got: {0:?}")] |
| GetString(Value), |
| |
| #[error("Expected Value::Enum, got: {0:?}")] |
| GetEnum(Value), |
| |
| #[error("Fixed size mismatch, expected: {size}, got: {n}")] |
| CompareFixedSizes { size: usize, n: usize }, |
| |
| #[error("String expected for fixed, got: {0:?}")] |
| GetStringForFixed(Value), |
| |
| #[error("Enum default {symbol:?} is not among allowed symbols {symbols:?}")] |
| GetEnumDefault { |
| symbol: String, |
| symbols: Vec<String>, |
| }, |
| |
| #[error("Enum value index {index} is out of bounds {nsymbols}")] |
| GetEnumValue { index: usize, nsymbols: usize }, |
| |
| #[error("Key {0} not found in decimal metadata JSON")] |
| GetDecimalMetadataFromJson(&'static str), |
| |
| #[error("Could not find matching type in {schema:?} for {value:?}")] |
| FindUnionVariant { schema: UnionSchema, value: Value }, |
| |
| #[error("Union type should not be empty")] |
| EmptyUnion, |
| |
| #[error("Array({expected:?}) expected, got {other:?}")] |
| GetArray { expected: SchemaKind, other: Value }, |
| |
| #[error("Map({expected:?}) expected, got {other:?}")] |
| GetMap { expected: SchemaKind, other: Value }, |
| |
| #[error("Record with fields {expected:?} expected, got {other:?}")] |
| GetRecord { |
| expected: Vec<(String, SchemaKind)>, |
| other: Value, |
| }, |
| |
| #[error("No `name` field")] |
| GetNameField, |
| |
| #[error("No `name` in record field")] |
| GetNameFieldFromRecord, |
| |
| #[error("Unions may not directly contain a union")] |
| GetNestedUnion, |
| |
| #[error( |
| "Found two different maps while building Union: Schema::Map({0:?}), Schema::Map({1:?})" |
| )] |
| GetUnionDuplicateMap(Schema, Schema), |
| |
| #[error( |
| "Found two different arrays while building Union: Schema::Array({0:?}), Schema::Array({1:?})" |
| )] |
| GetUnionDuplicateArray(Schema, Schema), |
| |
| #[error("Unions cannot contain duplicate types, found at least two {0:?}")] |
| GetUnionDuplicate(SchemaKind), |
| |
| #[error("Unions cannot contain more than one named schema with the same name: {0}")] |
| GetUnionDuplicateNamedSchemas(String), |
| |
| #[error("One union type {0:?} must match the `default`'s value type {1:?}")] |
| GetDefaultUnion(SchemaKind, ValueKind), |
| |
| #[error("`default`'s value type of field `{0}` in `{1}` must be a `{2:#}`. Got: {3:?}")] |
| GetDefaultRecordField(String, String, String, serde_json::Value), |
| |
| #[error("JSON number {0} could not be converted into an Avro value as it's too large")] |
| JsonNumberTooLarge(serde_json::Number), |
| |
| #[error("JSON value {0} claims to be u64 but cannot be converted")] |
| GetU64FromJson(serde_json::Number), |
| |
| #[error("JSON value {0} claims to be i64 but cannot be converted")] |
| GetI64FromJson(serde_json::Number), |
| |
| #[error("Cannot convert u64 to usize: {1}")] |
| ConvertU64ToUsize(#[source] std::num::TryFromIntError, u64), |
| |
| #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")] |
| #[error("Cannot convert u32 to usize: {1}")] |
| ConvertU32ToUsize(#[source] std::num::TryFromIntError, u32), |
| |
| #[error("Cannot convert i64 to usize: {1}")] |
| ConvertI64ToUsize(#[source] std::num::TryFromIntError, i64), |
| |
| #[error("Cannot convert i32 to usize: {1}")] |
| ConvertI32ToUsize(#[source] std::num::TryFromIntError, i32), |
| |
| #[error("Cannot convert i64 to u64: {1}")] |
| ConvertI64ToU64(#[source] std::num::TryFromIntError, i64), |
| |
| #[error("Cannot convert i32 to u64: {1}")] |
| ConvertI32ToU64(#[source] std::num::TryFromIntError, i32), |
| |
| #[error("Cannot convert i64 to u128: {1}")] |
| ConvertI64ToU128(#[source] std::num::TryFromIntError, i64), |
| |
| #[error("Cannot convert i32 to u128: {1}")] |
| ConvertI32ToU128(#[source] std::num::TryFromIntError, i32), |
| |
| #[error("Cannot convert usize to i64: {1}")] |
| ConvertUsizeToI64(#[source] std::num::TryFromIntError, usize), |
| |
| #[error("Invalid JSON value for decimal precision/scale integer: {0}")] |
| GetPrecisionOrScaleFromJson(serde_json::Number), |
| |
| #[error("Failed to parse schema from JSON")] |
| ParseSchemaJson(#[source] serde_json::Error), |
| |
| #[error("Failed to read schema")] |
| ReadSchemaFromReader(#[source] std::io::Error), |
| |
| #[error("Must be a JSON string, object or array")] |
| ParseSchemaFromValidJson, |
| |
| #[error("Unknown primitive type: {0}")] |
| ParsePrimitive(String), |
| |
| #[error("Unknown primitive type: '{0}'. Did you mean '{1}' ?")] |
| ParsePrimitiveSimilar(String, &'static str), |
| |
| #[error("invalid JSON for {key:?}: {value:?}")] |
| GetDecimalMetadataValueFromJson { |
| key: String, |
| value: serde_json::Value, |
| }, |
| |
| #[error("The decimal precision ({precision}) must be bigger or equal to the scale ({scale})")] |
| DecimalPrecisionLessThanScale { precision: usize, scale: usize }, |
| |
| #[error("The decimal precision ({precision}) must be a positive number")] |
| DecimalPrecisionMuBePositive { precision: usize }, |
| |
| #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")] |
| #[error("Unreadable big decimal sign")] |
| BigDecimalSign, |
| |
| #[error("Unreadable length for big decimal inner bytes: {0}")] |
| BigDecimalLen(#[source] Box<Error>), |
| |
| #[error("Unreadable big decimal scale")] |
| BigDecimalScale, |
| |
| #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")] |
| #[error("Unexpected `type` {0} variant for `logicalType`")] |
| GetLogicalTypeVariant(serde_json::Value), |
| |
| #[error("No `type` field found for `logicalType`")] |
| GetLogicalTypeField, |
| |
| #[error("logicalType must be a string, but is {0:?}")] |
| GetLogicalTypeFieldType(serde_json::Value), |
| |
| #[error("Unknown complex type: {0}")] |
| GetComplexType(serde_json::Value), |
| |
| #[error("No `type` in complex type")] |
| GetComplexTypeField, |
| |
| #[error("No `type` in record field")] |
| GetRecordFieldTypeField, |
| |
| #[error("No `fields` in record")] |
| GetRecordFieldsJson, |
| |
| #[error("No `symbols` field in enum")] |
| GetEnumSymbolsField, |
| |
| #[error("Unable to parse `symbols` in enum")] |
| GetEnumSymbols, |
| |
| #[error("Invalid enum symbol name {0}")] |
| EnumSymbolName(String), |
| |
| #[error("Invalid field name {0}")] |
| FieldName(String), |
| |
| #[error("Duplicate field name {0}")] |
| FieldNameDuplicate(String), |
| |
| #[error("Invalid schema name {0}. It must match the regex '{1}'")] |
| InvalidSchemaName(String, &'static str), |
| |
| #[error("Invalid namespace {0}. It must match the regex '{1}'")] |
| InvalidNamespace(String, &'static str), |
| |
| #[error( |
| "Invalid schema: There is no type called '{0}', if you meant to define a non-primitive schema, it should be defined inside `type` attribute." |
| )] |
| InvalidSchemaRecord(String), |
| |
| #[error("Duplicate enum symbol {0}")] |
| EnumSymbolDuplicate(String), |
| |
| #[error("Default value for an enum must be a string! Got: {0}")] |
| EnumDefaultWrongType(serde_json::Value), |
| |
| #[error("Default value for an array must be an array! Got: {0}")] |
| ArrayDefaultWrongType(serde_json::Value), |
| |
| #[error("Default value for an array must be an array of {0}! Found: {1:?}")] |
| ArrayDefaultWrongInnerType(Schema, Value), |
| |
| #[error("Default value for a map must be an object! Got: {0}")] |
| MapDefaultWrongType(serde_json::Value), |
| |
| #[error("Default value for a map must be an object with (String, {0})! Found: (String, {1:?})")] |
| MapDefaultWrongInnerType(Schema, Value), |
| |
| #[error("No `items` in array")] |
| GetArrayItemsField, |
| |
| #[error("No `values` in map")] |
| GetMapValuesField, |
| |
| #[error("Fixed schema `size` value must be a positive integer: {0}")] |
| GetFixedSizeFieldPositive(serde_json::Value), |
| |
| #[error("Fixed schema has no `size`")] |
| GetFixedSizeField, |
| |
| #[deprecated(since = "0.22.0", note = "This error variant is not generated anymore")] |
| #[error("Fixed schema's default value length ({0}) does not match its size ({1})")] |
| FixedDefaultLenSizeMismatch(usize, u64), |
| |
| #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")] |
| #[error("Failed to compress with flate: {0}")] |
| DeflateCompress(#[source] std::io::Error), |
| |
| // no longer possible after migration from libflate to miniz_oxide |
| #[deprecated(since = "0.19.0", note = "This error can no longer occur")] |
| #[error("Failed to finish flate compressor: {0}")] |
| DeflateCompressFinish(#[source] std::io::Error), |
| |
| #[error("Failed to decompress with flate: {0}")] |
| DeflateDecompress(#[source] std::io::Error), |
| |
| #[cfg(feature = "snappy")] |
| #[error("Failed to compress with snappy: {0}")] |
| SnappyCompress(#[source] snap::Error), |
| |
| #[cfg(feature = "snappy")] |
| #[error("Failed to get snappy decompression length: {0}")] |
| GetSnappyDecompressLen(#[source] snap::Error), |
| |
| #[cfg(feature = "snappy")] |
| #[error("Failed to decompress with snappy: {0}")] |
| SnappyDecompress(#[source] snap::Error), |
| |
| #[error("Failed to compress with zstd: {0}")] |
| ZstdCompress(#[source] std::io::Error), |
| |
| #[error("Failed to decompress with zstd: {0}")] |
| ZstdDecompress(#[source] std::io::Error), |
| |
| #[error("Failed to read header: {0}")] |
| ReadHeader(#[source] std::io::Error), |
| |
| #[error("wrong magic in header")] |
| HeaderMagic, |
| |
| #[error("Message Header mismatch. Expected: {0:?}. Actual: {1:?}")] |
| SingleObjectHeaderMismatch(Vec<u8>, Vec<u8>), |
| |
| #[error("Failed to get JSON from avro.schema key in map")] |
| GetAvroSchemaFromMap, |
| |
| #[error("no metadata in header")] |
| GetHeaderMetadata, |
| |
| #[error("Failed to read marker bytes: {0}")] |
| ReadMarker(#[source] std::io::Error), |
| |
| #[error("Failed to read block marker bytes: {0}")] |
| ReadBlockMarker(#[source] std::io::Error), |
| |
| #[error("Read into buffer failed: {0}")] |
| ReadIntoBuf(#[source] std::io::Error), |
| |
| #[error( |
| "Invalid sync marker! The sync marker in the data block \ |
| doesn't match the file header's sync marker. This likely \ |
| indicates data corruption, truncated file, or incorrectly \ |
| concatenated Avro files. Verify file integrity and ensure \ |
| proper file transmission or creation." |
| )] |
| GetBlockMarker, |
| |
| #[error("Overflow when decoding integer value")] |
| IntegerOverflow, |
| |
| #[error("Failed to read bytes for decoding variable length integer: {0}")] |
| ReadVariableIntegerBytes(#[source] std::io::Error), |
| |
| #[error("Decoded integer out of range for i32: {1}: {0}")] |
| ZagI32(#[source] std::num::TryFromIntError, i64), |
| |
| #[error("Did not read any bytes, block is corrupt")] |
| ReadBlock, |
| |
| #[error("Failed to serialize value into Avro value: {0}")] |
| SerializeValue(String), |
| |
| #[error("Failed to serialize value of type `{value_type}` using Schema::{schema:?}: {value}")] |
| SerializeValueWithSchema { |
| value_type: &'static str, |
| value: String, |
| schema: Schema, |
| }, |
| |
| #[error("{position} is not a valid index for fields in {schema:?}")] |
| SerializeRecordUnknownFieldIndex { |
| position: usize, |
| schema: RecordSchema, |
| }, |
| |
| #[error("Failed to serialize field '{field_name}' of record {record_schema:?}: {error}")] |
| SerializeRecordFieldWithSchema { |
| field_name: String, |
| record_schema: RecordSchema, |
| error: String, |
| }, |
| |
| #[error("Missing default for skipped field '{field_name}' of schema {schema:?}")] |
| MissingDefaultForSkippedField { |
| field_name: String, |
| schema: RecordSchema, |
| }, |
| |
| #[error("Failed to deserialize Avro value into value: {0}")] |
| DeserializeValue(String), |
| |
| #[error("Failed to deserialize value of type {value_type} using schema {schema:?}: {value}")] |
| DeserializeSchemaAware { |
| value_type: &'static str, |
| value: String, |
| schema: Schema, |
| }, |
| |
| #[error("Only expected `deserialize_identifier` to be called but `{0}` was called")] |
| DeserializeIdentifier(&'static str), |
| |
| #[error("Failed to write buffer bytes during flush: {0}")] |
| WriteBytes(#[source] std::io::Error), |
| |
| #[error("Failed to flush inner writer during flush: {0}")] |
| FlushWriter(#[source] std::io::Error), |
| |
| #[error("Failed to write marker: {0}")] |
| WriteMarker(#[source] std::io::Error), |
| |
| #[error("Failed to convert JSON to string: {0}")] |
| ConvertJsonToString(#[source] serde_json::Error), |
| |
| /// Error while converting float to JSON value |
| #[error("failed to convert avro float to json: {0}")] |
| ConvertF64ToJson(f64), |
| |
| /// Error while resolving [`Schema::Ref`] |
| #[error("Unresolved schema reference: {0}")] |
| SchemaResolutionError(Name), |
| |
| #[error("The file metadata is already flushed.")] |
| FileHeaderAlreadyWritten, |
| |
| #[error("Metadata keys starting with 'avro.' are reserved for internal usage: {0}.")] |
| InvalidMetadataKey(String), |
| |
| /// Error when two named schema have the same fully qualified name |
| #[error("Two named schema defined for same fullname: {0}.")] |
| AmbiguousSchemaDefinition(Name), |
| |
| #[error("Signed decimal bytes length {0} not equal to fixed schema size {1}.")] |
| EncodeDecimalAsFixedError(usize, usize), |
| |
| #[error("There is no entry for '{0}' in the lookup table: {1}.")] |
| NoEntryInLookupTable(String, String), |
| |
| #[error("Can only encode value type {value_kind:?} as one of {supported_schema:?}")] |
| EncodeValueAsSchemaError { |
| value_kind: ValueKind, |
| supported_schema: Vec<SchemaKind>, |
| }, |
| #[error("Internal buffer not drained properly. Re-initialize the single object writer struct!")] |
| IllegalSingleObjectWriterState, |
| |
| #[error("Codec '{0}' is not supported/enabled")] |
| CodecNotSupported(String), |
| |
| #[error("Invalid Avro data! Cannot read codec type from value that is not Value::Bytes.")] |
| BadCodecMetadata, |
| |
| #[error("Cannot convert a slice to Uuid: {0}")] |
| UuidFromSlice(#[source] uuid::Error), |
| |
| #[error("Expected String for Map key when serializing a flattened struct")] |
| MapFieldExpectedString, |
| |
| #[error("No key for value when serializing a map")] |
| MapNoKey, |
| |
| #[error( |
| "The implementation of `SchemaNameValidator` is incorrect! It returned an out-of-bounds index or provided a regex that did not capture a group named `name`" |
| )] |
| InvalidSchemaNameValidatorImplementation, |
| |
| #[error( |
| "Not all tuple fields were serialized, expected to serialize element at position {position} of a {total_elements}-tuple but `SerializeTuple::end()` was called" |
| )] |
| SerializeTupleMissingElements { |
| position: usize, |
| total_elements: usize, |
| }, |
| } |
| |
| #[derive(thiserror::Error, PartialEq)] |
| pub enum CompatibilityError { |
| #[error( |
| "Incompatible schema types! Writer schema is '{writer_schema_type}', but reader schema is '{reader_schema_type}'" |
| )] |
| WrongType { |
| writer_schema_type: String, |
| reader_schema_type: String, |
| }, |
| |
| #[error("Incompatible schema types! The {schema_type} should have been {expected_type:?}")] |
| TypeExpected { |
| schema_type: String, |
| expected_type: Vec<SchemaKind>, |
| }, |
| |
| #[error( |
| "Incompatible schemata! Field '{0}' in reader schema does not match the type in the writer schema" |
| )] |
| FieldTypeMismatch(String, #[source] Box<CompatibilityError>), |
| |
| #[error("Incompatible schemata! Field '{0}' in reader schema must have a default value")] |
| MissingDefaultValue(String), |
| |
| #[error("Incompatible schemata! Reader's symbols contain none of the writer's symbols")] |
| MissingSymbols, |
| |
| #[error("Incompatible schemata! All elements in union must match for both schemas")] |
| MissingUnionElements, |
| |
| #[error("Incompatible schemata! At least one element in the union must match the schema")] |
| SchemaMismatchAllUnionElements, |
| |
| #[error("Incompatible schemata! Size doesn't match for fixed")] |
| FixedMismatch, |
| |
| #[error( |
| "Incompatible schemata! Decimal precision and/or scale don't match, reader: ({r_precision},{r_scale}), writer: ({w_precision},{w_scale})" |
| )] |
| DecimalMismatch { |
| r_precision: usize, |
| r_scale: usize, |
| w_precision: usize, |
| w_scale: usize, |
| }, |
| |
| #[error( |
| "Incompatible schemata! The name must be the same for both schemas. Writer's name {writer_name} and reader's name {reader_name}" |
| )] |
| NameMismatch { |
| writer_name: String, |
| reader_name: String, |
| }, |
| |
| #[error( |
| "Incompatible schemata! Unknown type for '{0}'. Make sure that the type is a valid one" |
| )] |
| Inconclusive(String), |
| } |
| |
| impl serde::ser::Error for Details { |
| fn custom<T: fmt::Display>(msg: T) -> Self { |
| Details::SerializeValue(msg.to_string()) |
| } |
| } |
| |
| impl serde::de::Error for Details { |
| fn custom<T: fmt::Display>(msg: T) -> Self { |
| Details::DeserializeValue(msg.to_string()) |
| } |
| } |
| |
| impl fmt::Debug for Details { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| let mut msg = self.to_string(); |
| if let Some(e) = self.source() { |
| msg.extend([": ", &e.to_string()]); |
| } |
| write!(f, "{msg}") |
| } |
| } |
| |
| impl fmt::Debug for CompatibilityError { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| let mut msg = self.to_string(); |
| if let Some(e) = self.source() { |
| msg.extend([": ", &e.to_string()]); |
| } |
| write!(f, "{msg}") |
| } |
| } |