Skip to main content

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