apache_avro/
error.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::{
19    schema::{Name, Schema, SchemaKind, UnionSchema},
20    types::{Value, ValueKind},
21};
22use std::{error::Error as _, fmt};
23
24/// Errors encountered by Avro.
25///
26/// To inspect the details of the error use [`details`](Self::details) or [`into_details`](Self::into_details)
27/// to get a [`Details`] which contains more precise error information.
28///
29/// See [`Details`] for all possible errors.
30#[derive(thiserror::Error, Debug)]
31#[repr(transparent)]
32#[error(transparent)]
33pub struct Error {
34    details: Box<Details>,
35}
36
37impl Error {
38    pub fn new(details: Details) -> Self {
39        Self {
40            details: Box::new(details),
41        }
42    }
43
44    pub fn details(&self) -> &Details {
45        &self.details
46    }
47
48    pub fn into_details(self) -> Details {
49        *self.details
50    }
51}
52
53impl From<Details> for Error {
54    fn from(details: Details) -> Self {
55        Self::new(details)
56    }
57}
58
59impl serde::ser::Error for Error {
60    fn custom<T: fmt::Display>(msg: T) -> Self {
61        Self::new(<Details as serde::ser::Error>::custom(msg))
62    }
63}
64
65impl serde::de::Error for Error {
66    fn custom<T: fmt::Display>(msg: T) -> Self {
67        Self::new(<Details as serde::de::Error>::custom(msg))
68    }
69}
70
71#[derive(thiserror::Error)]
72pub enum Details {
73    #[error("Bad Snappy CRC32; expected {expected:x} but got {actual:x}")]
74    SnappyCrc32 { expected: u32, actual: u32 },
75
76    #[error("Invalid u8 for bool: {0}")]
77    BoolValue(u8),
78
79    #[error("Not a fixed value, required for decimal with fixed schema: {0:?}")]
80    FixedValue(Value),
81
82    #[error("Not a bytes value, required for decimal with bytes schema: {0:?}")]
83    BytesValue(Value),
84
85    #[error("Not a string value, required for uuid: {0:?}")]
86    GetUuidFromStringValue(Value),
87
88    #[error("Two schemas with the same fullname were given: {0:?}")]
89    NameCollision(String),
90
91    #[error("Not a fixed or bytes type, required for decimal schema, got: {0:?}")]
92    ResolveDecimalSchema(SchemaKind),
93
94    #[error("Invalid utf-8 string")]
95    ConvertToUtf8(#[source] std::string::FromUtf8Error),
96
97    #[error("Invalid utf-8 string")]
98    ConvertToUtf8Error(#[source] std::str::Utf8Error),
99
100    /// Describes errors happened while validating Avro data.
101    #[error("Value does not match schema")]
102    Validation,
103
104    /// Describes errors happened while validating Avro data.
105    #[error("Value {value:?} does not match schema {schema:?}: Reason: {reason}")]
106    ValidationWithReason {
107        value: Value,
108        schema: Schema,
109        reason: String,
110    },
111
112    #[error(
113        "Unable to allocate {desired} bytes (maximum allowed: {maximum}). Change the limit using `apache_avro::util::max_allocation_bytes`"
114    )]
115    MemoryAllocation { desired: usize, maximum: usize },
116
117    /// Describe a specific error happening with decimal representation
118    #[error(
119        "Number of bytes requested for decimal sign extension {requested} is less than the number of bytes needed to decode {needed}"
120    )]
121    SignExtend { requested: usize, needed: usize },
122
123    #[error("Failed to read boolean bytes: {0}")]
124    ReadBoolean(#[source] std::io::Error),
125
126    #[error("Failed to read bytes: {0}")]
127    ReadBytes(#[source] std::io::Error),
128
129    #[error("Failed to read string: {0}")]
130    ReadString(#[source] std::io::Error),
131
132    #[error("Failed to read double: {0}")]
133    ReadDouble(#[source] std::io::Error),
134
135    #[error("Failed to read float: {0}")]
136    ReadFloat(#[source] std::io::Error),
137
138    #[error("Failed to read duration: {0}")]
139    ReadDuration(#[source] std::io::Error),
140
141    #[error("Failed to read fixed number of bytes '{1}': : {0}")]
142    ReadFixed(#[source] std::io::Error, usize),
143
144    #[error("Failed to convert &str to UUID: {0}")]
145    ConvertStrToUuid(#[source] uuid::Error),
146
147    #[error("Failed to convert Fixed bytes to UUID. It must be exactly 16 bytes, got {0}")]
148    ConvertFixedToUuid(usize),
149
150    #[error("Failed to convert Fixed bytes to UUID: {0}")]
151    ConvertSliceToUuid(#[source] uuid::Error),
152
153    #[error("Map key is not a string; key type is {0:?}")]
154    MapKeyType(ValueKind),
155
156    #[error("Union index {index} out of bounds: {num_variants}")]
157    GetUnionVariant { index: i64, num_variants: usize },
158
159    #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")]
160    #[error("Enum symbol index out of bounds: {num_variants}")]
161    EnumSymbolIndex { index: usize, num_variants: usize },
162
163    #[error("Enum symbol not found {0}")]
164    GetEnumSymbol(String),
165
166    #[error("Unable to decode enum index")]
167    GetEnumUnknownIndexValue,
168
169    #[error("Scale {scale} is greater than precision {precision}")]
170    GetScaleAndPrecision { scale: usize, precision: usize },
171
172    #[error(
173        "Fixed type number of bytes {size} is not large enough to hold decimal values of precision {precision}"
174    )]
175    GetScaleWithFixedSize { size: usize, precision: usize },
176
177    #[error("Expected Value::Uuid, got: {0:?}")]
178    GetUuid(Value),
179
180    #[error("Expected Value::BigDecimal, got: {0:?}")]
181    GetBigDecimal(Value),
182
183    #[error("Fixed bytes of size 12 expected, got Fixed of size {0}")]
184    GetDurationFixedBytes(usize),
185
186    #[error("Expected Value::Duration or Value::Fixed(12), got: {0:?}")]
187    ResolveDuration(Value),
188
189    #[error("Expected Value::Decimal, Value::Bytes or Value::Fixed, got: {0:?}")]
190    ResolveDecimal(Value),
191
192    #[error("Missing field in record: {0:?}")]
193    GetField(String),
194
195    #[error("Unable to convert to u8, got {0:?}")]
196    GetU8(Value),
197
198    #[error("Precision {precision} too small to hold decimal values with {num_bytes} bytes")]
199    ComparePrecisionAndSize { precision: usize, num_bytes: usize },
200
201    #[error("Cannot convert length to i32: {1}")]
202    ConvertLengthToI32(#[source] std::num::TryFromIntError, usize),
203
204    #[error("Expected Value::Date or Value::Int, got: {0:?}")]
205    GetDate(Value),
206
207    #[error("Expected Value::TimeMillis or Value::Int, got: {0:?}")]
208    GetTimeMillis(Value),
209
210    #[error("Expected Value::TimeMicros, Value::Long or Value::Int, got: {0:?}")]
211    GetTimeMicros(Value),
212
213    #[error("Expected Value::TimestampMillis, Value::Long or Value::Int, got: {0:?}")]
214    GetTimestampMillis(Value),
215
216    #[error("Expected Value::TimestampMicros, Value::Long or Value::Int, got: {0:?}")]
217    GetTimestampMicros(Value),
218
219    #[error("Expected Value::TimestampNanos, Value::Long or Value::Int, got: {0:?}")]
220    GetTimestampNanos(Value),
221
222    #[error("Expected Value::LocalTimestampMillis, Value::Long or Value::Int, got: {0:?}")]
223    GetLocalTimestampMillis(Value),
224
225    #[error("Expected Value::LocalTimestampMicros, Value::Long or Value::Int, got: {0:?}")]
226    GetLocalTimestampMicros(Value),
227
228    #[error("Expected Value::LocalTimestampNanos, Value::Long or Value::Int, got: {0:?}")]
229    GetLocalTimestampNanos(Value),
230
231    #[error("Expected Value::Null, got: {0:?}")]
232    GetNull(Value),
233
234    #[error("Expected Value::Boolean, got: {0:?}")]
235    GetBoolean(Value),
236
237    #[error("Expected Value::Int, got: {0:?}")]
238    GetInt(Value),
239
240    #[error("Expected Value::Long or Value::Int, got: {0:?}")]
241    GetLong(Value),
242
243    #[error(r#"Expected Value::Double, Value::Float, Value::Int, Value::Long or Value::String ("NaN", "INF", "Infinity", "-INF" or "-Infinity"), got: {0:?}"#)]
244    GetDouble(Value),
245
246    #[error(r#"Expected Value::Float, Value::Double, Value::Int, Value::Long or Value::String ("NaN", "INF", "Infinity", "-INF" or "-Infinity"), got: {0:?}"#)]
247    GetFloat(Value),
248
249    #[error("Expected Value::Bytes, got: {0:?}")]
250    GetBytes(Value),
251
252    #[error("Expected Value::String, Value::Bytes or Value::Fixed, got: {0:?}")]
253    GetString(Value),
254
255    #[error("Expected Value::Enum, got: {0:?}")]
256    GetEnum(Value),
257
258    #[error("Fixed size mismatch, expected: {size}, got: {n}")]
259    CompareFixedSizes { size: usize, n: usize },
260
261    #[error("String expected for fixed, got: {0:?}")]
262    GetStringForFixed(Value),
263
264    #[error("Enum default {symbol:?} is not among allowed symbols {symbols:?}")]
265    GetEnumDefault {
266        symbol: String,
267        symbols: Vec<String>,
268    },
269
270    #[error("Enum value index {index} is out of bounds {nsymbols}")]
271    GetEnumValue { index: usize, nsymbols: usize },
272
273    #[error("Key {0} not found in decimal metadata JSON")]
274    GetDecimalMetadataFromJson(&'static str),
275
276    #[error("Could not find matching type in {schema:?} for {value:?}")]
277    FindUnionVariant { schema: UnionSchema, value: Value },
278
279    #[error("Union type should not be empty")]
280    EmptyUnion,
281
282    #[error("Array({expected:?}) expected, got {other:?}")]
283    GetArray { expected: SchemaKind, other: Value },
284
285    #[error("Map({expected:?}) expected, got {other:?}")]
286    GetMap { expected: SchemaKind, other: Value },
287
288    #[error("Record with fields {expected:?} expected, got {other:?}")]
289    GetRecord {
290        expected: Vec<(String, SchemaKind)>,
291        other: Value,
292    },
293
294    #[error("No `name` field")]
295    GetNameField,
296
297    #[error("No `name` in record field")]
298    GetNameFieldFromRecord,
299
300    #[error("Unions may not directly contain a union")]
301    GetNestedUnion,
302
303    #[error(
304        "Found two different maps while building Union: Schema::Map({0:?}), Schema::Map({1:?})"
305    )]
306    GetUnionDuplicateMap(Schema, Schema),
307
308    #[error(
309        "Found two different arrays while building Union: Schema::Array({0:?}), Schema::Array({1:?})"
310    )]
311    GetUnionDuplicateArray(Schema, Schema),
312
313    #[error("Unions cannot contain duplicate types, found at least two {0:?}")]
314    GetUnionDuplicate(SchemaKind),
315
316    #[error("Unions cannot contain more than one named schema with the same name: {0}")]
317    GetUnionDuplicateNamedSchemas(String),
318
319    #[error("One union type {0:?} must match the `default`'s value type {1:?}")]
320    GetDefaultUnion(SchemaKind, ValueKind),
321
322    #[error("`default`'s value type of field `{0}` in `{1}` must be a `{2:#}`. Got: {3:?}")]
323    GetDefaultRecordField(String, String, String, serde_json::Value),
324
325    #[error("JSON number {0} could not be converted into an Avro value as it's too large")]
326    JsonNumberTooLarge(serde_json::Number),
327
328    #[error("JSON value {0} claims to be u64 but cannot be converted")]
329    GetU64FromJson(serde_json::Number),
330
331    #[error("JSON value {0} claims to be i64 but cannot be converted")]
332    GetI64FromJson(serde_json::Number),
333
334    #[error("Cannot convert u64 to usize: {1}")]
335    ConvertU64ToUsize(#[source] std::num::TryFromIntError, u64),
336
337    #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")]
338    #[error("Cannot convert u32 to usize: {1}")]
339    ConvertU32ToUsize(#[source] std::num::TryFromIntError, u32),
340
341    #[error("Cannot convert i64 to usize: {1}")]
342    ConvertI64ToUsize(#[source] std::num::TryFromIntError, i64),
343
344    #[error("Cannot convert i32 to usize: {1}")]
345    ConvertI32ToUsize(#[source] std::num::TryFromIntError, i32),
346
347    #[error("Cannot convert i64 to u64: {1}")]
348    ConvertI64ToU64(#[source] std::num::TryFromIntError, i64),
349
350    #[error("Cannot convert i32 to u64: {1}")]
351    ConvertI32ToU64(#[source] std::num::TryFromIntError, i32),
352
353    #[error("Cannot convert i64 to u128: {1}")]
354    ConvertI64ToU128(#[source] std::num::TryFromIntError, i64),
355
356    #[error("Cannot convert i32 to u128: {1}")]
357    ConvertI32ToU128(#[source] std::num::TryFromIntError, i32),
358
359    #[error("Cannot convert usize to i64: {1}")]
360    ConvertUsizeToI64(#[source] std::num::TryFromIntError, usize),
361
362    #[error("Invalid JSON value for decimal precision/scale integer: {0}")]
363    GetPrecisionOrScaleFromJson(serde_json::Number),
364
365    #[error("Failed to parse schema from JSON")]
366    ParseSchemaJson(#[source] serde_json::Error),
367
368    #[error("Failed to read schema")]
369    ReadSchemaFromReader(#[source] std::io::Error),
370
371    #[error("Must be a JSON string, object or array")]
372    ParseSchemaFromValidJson,
373
374    #[error("Unknown primitive type: {0}")]
375    ParsePrimitive(String),
376
377    #[error("Unknown primitive type: '{0}'. Did you mean '{1}' ?")]
378    ParsePrimitiveSimilar(String, &'static str),
379
380    #[error("invalid JSON for {key:?}: {value:?}")]
381    GetDecimalMetadataValueFromJson {
382        key: String,
383        value: serde_json::Value,
384    },
385
386    #[error("The decimal precision ({precision}) must be bigger or equal to the scale ({scale})")]
387    DecimalPrecisionLessThanScale { precision: usize, scale: usize },
388
389    #[error("The decimal precision ({precision}) must be a positive number")]
390    DecimalPrecisionMuBePositive { precision: usize },
391
392    #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")]
393    #[error("Unreadable big decimal sign")]
394    BigDecimalSign,
395
396    #[error("Unreadable length for big decimal inner bytes: {0}")]
397    BigDecimalLen(#[source] Box<Error>),
398
399    #[error("Unreadable big decimal scale")]
400    BigDecimalScale,
401
402    #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")]
403    #[error("Unexpected `type` {0} variant for `logicalType`")]
404    GetLogicalTypeVariant(serde_json::Value),
405
406    #[error("No `type` field found for `logicalType`")]
407    GetLogicalTypeField,
408
409    #[error("logicalType must be a string, but is {0:?}")]
410    GetLogicalTypeFieldType(serde_json::Value),
411
412    #[error("Unknown complex type: {0}")]
413    GetComplexType(serde_json::Value),
414
415    #[error("No `type` in complex type")]
416    GetComplexTypeField,
417
418    #[error("No `type` in record field")]
419    GetRecordFieldTypeField,
420
421    #[error("No `fields` in record")]
422    GetRecordFieldsJson,
423
424    #[error("No `symbols` field in enum")]
425    GetEnumSymbolsField,
426
427    #[error("Unable to parse `symbols` in enum")]
428    GetEnumSymbols,
429
430    #[error("Invalid enum symbol name {0}")]
431    EnumSymbolName(String),
432
433    #[error("Invalid field name {0}")]
434    FieldName(String),
435
436    #[error("Duplicate field name {0}")]
437    FieldNameDuplicate(String),
438
439    #[error("Invalid schema name {0}. It must match the regex '{1}'")]
440    InvalidSchemaName(String, &'static str),
441
442    #[error("Invalid namespace {0}. It must match the regex '{1}'")]
443    InvalidNamespace(String, &'static str),
444
445    #[error(
446        "Invalid schema: There is no type called '{0}', if you meant to define a non-primitive schema, it should be defined inside `type` attribute."
447    )]
448    InvalidSchemaRecord(String),
449
450    #[error("Duplicate enum symbol {0}")]
451    EnumSymbolDuplicate(String),
452
453    #[error("Default value for an enum must be a string! Got: {0}")]
454    EnumDefaultWrongType(serde_json::Value),
455
456    #[error("Default value for an array must be an array! Got: {0}")]
457    ArrayDefaultWrongType(serde_json::Value),
458
459    #[error("Default value for an array must be an array of {0}! Found: {1:?}")]
460    ArrayDefaultWrongInnerType(Schema, Value),
461
462    #[error("Default value for a map must be an object! Got: {0}")]
463    MapDefaultWrongType(serde_json::Value),
464
465    #[error("Default value for a map must be an object with (String, {0})! Found: (String, {1:?})")]
466    MapDefaultWrongInnerType(Schema, Value),
467
468    #[error("No `items` in array")]
469    GetArrayItemsField,
470
471    #[error("No `values` in map")]
472    GetMapValuesField,
473
474    #[error("Fixed schema `size` value must be a positive integer: {0}")]
475    GetFixedSizeFieldPositive(serde_json::Value),
476
477    #[error("Fixed schema has no `size`")]
478    GetFixedSizeField,
479
480    #[deprecated(since = "0.22.0", note = "This error variant is not generated anymore")]
481    #[error("Fixed schema's default value length ({0}) does not match its size ({1})")]
482    FixedDefaultLenSizeMismatch(usize, u64),
483
484    #[deprecated(since = "0.20.0", note = "This error variant is not generated anymore")]
485    #[error("Failed to compress with flate: {0}")]
486    DeflateCompress(#[source] std::io::Error),
487
488    // no longer possible after migration from libflate to miniz_oxide
489    #[deprecated(since = "0.19.0", note = "This error can no longer occur")]
490    #[error("Failed to finish flate compressor: {0}")]
491    DeflateCompressFinish(#[source] std::io::Error),
492
493    #[error("Failed to decompress with flate: {0}")]
494    DeflateDecompress(#[source] std::io::Error),
495
496    #[cfg(feature = "snappy")]
497    #[error("Failed to compress with snappy: {0}")]
498    SnappyCompress(#[source] snap::Error),
499
500    #[cfg(feature = "snappy")]
501    #[error("Failed to get snappy decompression length: {0}")]
502    GetSnappyDecompressLen(#[source] snap::Error),
503
504    #[cfg(feature = "snappy")]
505    #[error("Failed to decompress with snappy: {0}")]
506    SnappyDecompress(#[source] snap::Error),
507
508    #[error("Failed to compress with zstd: {0}")]
509    ZstdCompress(#[source] std::io::Error),
510
511    #[error("Failed to decompress with zstd: {0}")]
512    ZstdDecompress(#[source] std::io::Error),
513
514    #[error("Failed to read header: {0}")]
515    ReadHeader(#[source] std::io::Error),
516
517    #[error("wrong magic in header")]
518    HeaderMagic,
519
520    #[error("Message Header mismatch. Expected: {0:?}. Actual: {1:?}")]
521    SingleObjectHeaderMismatch(Vec<u8>, Vec<u8>),
522
523    #[error("Failed to get JSON from avro.schema key in map")]
524    GetAvroSchemaFromMap,
525
526    #[error("no metadata in header")]
527    GetHeaderMetadata,
528
529    #[error("Failed to read marker bytes: {0}")]
530    ReadMarker(#[source] std::io::Error),
531
532    #[error("Failed to read block marker bytes: {0}")]
533    ReadBlockMarker(#[source] std::io::Error),
534
535    #[error("Read into buffer failed: {0}")]
536    ReadIntoBuf(#[source] std::io::Error),
537
538    #[error(
539        "Invalid sync marker! The sync marker in the data block \
540        doesn't match the file header's sync marker. This likely \
541        indicates data corruption, truncated file, or incorrectly \
542        concatenated Avro files. Verify file integrity and ensure \
543        proper file transmission or creation."
544    )]
545    GetBlockMarker,
546
547    #[error("Overflow when decoding integer value")]
548    IntegerOverflow,
549
550    #[error("Failed to read bytes for decoding variable length integer: {0}")]
551    ReadVariableIntegerBytes(#[source] std::io::Error),
552
553    #[error("Decoded integer out of range for i32: {1}: {0}")]
554    ZagI32(#[source] std::num::TryFromIntError, i64),
555
556    #[error("unable to read block")]
557    ReadBlock,
558
559    #[error("Failed to serialize value into Avro value: {0}")]
560    SerializeValue(String),
561
562    #[error("Failed to serialize value of type {value_type} using schema {schema:?}: {value}")]
563    SerializeValueWithSchema {
564        value_type: &'static str,
565        value: String,
566        schema: Schema,
567    },
568
569    #[error("Failed to serialize field '{field_name}' for record {record_schema:?}: {error}")]
570    SerializeRecordFieldWithSchema {
571        field_name: String,
572        record_schema: Schema,
573        error: Box<Error>,
574    },
575
576    #[error("Missing default for skipped field '{field_name}' for schema {schema:?}")]
577    MissingDefaultForSkippedField { field_name: String, schema: Schema },
578
579    #[error("Failed to deserialize Avro value into value: {0}")]
580    DeserializeValue(String),
581
582    #[error("Failed to write buffer bytes during flush: {0}")]
583    WriteBytes(#[source] std::io::Error),
584
585    #[error("Failed to flush inner writer during flush: {0}")]
586    FlushWriter(#[source] std::io::Error),
587
588    #[error("Failed to write marker: {0}")]
589    WriteMarker(#[source] std::io::Error),
590
591    #[error("Failed to convert JSON to string: {0}")]
592    ConvertJsonToString(#[source] serde_json::Error),
593
594    /// Error while converting float to JSON value
595    #[error("failed to convert avro float to json: {0}")]
596    ConvertF64ToJson(f64),
597
598    /// Error while resolving [`Schema::Ref`]
599    #[error("Unresolved schema reference: {0}")]
600    SchemaResolutionError(Name),
601
602    #[error("The file metadata is already flushed.")]
603    FileHeaderAlreadyWritten,
604
605    #[error("Metadata keys starting with 'avro.' are reserved for internal usage: {0}.")]
606    InvalidMetadataKey(String),
607
608    /// Error when two named schema have the same fully qualified name
609    #[error("Two named schema defined for same fullname: {0}.")]
610    AmbiguousSchemaDefinition(Name),
611
612    #[error("Signed decimal bytes length {0} not equal to fixed schema size {1}.")]
613    EncodeDecimalAsFixedError(usize, usize),
614
615    #[error("There is no entry for '{0}' in the lookup table: {1}.")]
616    NoEntryInLookupTable(String, String),
617
618    #[error("Can only encode value type {value_kind:?} as one of {supported_schema:?}")]
619    EncodeValueAsSchemaError {
620        value_kind: ValueKind,
621        supported_schema: Vec<SchemaKind>,
622    },
623    #[error("Internal buffer not drained properly. Re-initialize the single object writer struct!")]
624    IllegalSingleObjectWriterState,
625
626    #[error("Codec '{0}' is not supported/enabled")]
627    CodecNotSupported(String),
628
629    #[error("Invalid Avro data! Cannot read codec type from value that is not Value::Bytes.")]
630    BadCodecMetadata,
631
632    #[error("Cannot convert a slice to Uuid: {0}")]
633    UuidFromSlice(#[source] uuid::Error),
634
635    #[error("Expected String for Map key when serializing a flattened struct")]
636    MapFieldExpectedString,
637
638    #[error("No key for value when serializing a map")]
639    MapNoKey,
640
641    #[error(
642        "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`"
643    )]
644    InvalidSchemaNameValidatorImplementation,
645}
646
647#[derive(thiserror::Error, PartialEq)]
648pub enum CompatibilityError {
649    #[error(
650        "Incompatible schema types! Writer schema is '{writer_schema_type}', but reader schema is '{reader_schema_type}'"
651    )]
652    WrongType {
653        writer_schema_type: String,
654        reader_schema_type: String,
655    },
656
657    #[error("Incompatible schema types! The {schema_type} should have been {expected_type:?}")]
658    TypeExpected {
659        schema_type: String,
660        expected_type: Vec<SchemaKind>,
661    },
662
663    #[error(
664        "Incompatible schemata! Field '{0}' in reader schema does not match the type in the writer schema"
665    )]
666    FieldTypeMismatch(String, #[source] Box<CompatibilityError>),
667
668    #[error("Incompatible schemata! Field '{0}' in reader schema must have a default value")]
669    MissingDefaultValue(String),
670
671    #[error("Incompatible schemata! Reader's symbols contain none of the writer's symbols")]
672    MissingSymbols,
673
674    #[error("Incompatible schemata! All elements in union must match for both schemas")]
675    MissingUnionElements,
676
677    #[error("Incompatible schemata! At least one element in the union must match the schema")]
678    SchemaMismatchAllUnionElements,
679
680    #[error("Incompatible schemata! Size doesn't match for fixed")]
681    FixedMismatch,
682
683    #[error(
684        "Incompatible schemata! Decimal precision and/or scale don't match, reader: ({r_precision},{r_scale}), writer: ({w_precision},{w_scale})"
685    )]
686    DecimalMismatch {
687        r_precision: usize,
688        r_scale: usize,
689        w_precision: usize,
690        w_scale: usize,
691    },
692
693    #[error(
694        "Incompatible schemata! The name must be the same for both schemas. Writer's name {writer_name} and reader's name {reader_name}"
695    )]
696    NameMismatch {
697        writer_name: String,
698        reader_name: String,
699    },
700
701    #[error(
702        "Incompatible schemata! Unknown type for '{0}'. Make sure that the type is a valid one"
703    )]
704    Inconclusive(String),
705}
706
707impl serde::ser::Error for Details {
708    fn custom<T: fmt::Display>(msg: T) -> Self {
709        Details::SerializeValue(msg.to_string())
710    }
711}
712
713impl serde::de::Error for Details {
714    fn custom<T: fmt::Display>(msg: T) -> Self {
715        Details::DeserializeValue(msg.to_string())
716    }
717}
718
719impl fmt::Debug for Details {
720    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
721        let mut msg = self.to_string();
722        if let Some(e) = self.source() {
723            msg.extend([": ", &e.to_string()]);
724        }
725        write!(f, "{msg}")
726    }
727}
728
729impl fmt::Debug for CompatibilityError {
730    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
731        let mut msg = self.to_string();
732        if let Some(e) = self.source() {
733            msg.extend([": ", &e.to_string()]);
734        }
735        write!(f, "{msg}")
736    }
737}