1#![cfg_attr(docsrs, feature(rustdoc_internals))]
54#![cfg_attr(docsrs, allow(internal_features))]
55
56mod bigdecimal;
57mod bytes;
58mod codec;
59mod decimal;
60mod decode;
61mod duration;
62mod encode;
63
64#[cfg(doc)]
65pub mod documentation;
66pub mod error;
67pub mod headers;
68pub mod rabin;
69pub mod reader;
70pub mod schema;
71pub mod schema_compatibility;
72pub mod schema_equality;
73pub mod serde;
74pub mod types;
75pub mod util;
76pub mod validator;
77pub mod writer;
78
79#[expect(deprecated)]
80pub use crate::{
81 bigdecimal::BigDecimal,
82 bytes::{
83 serde_avro_bytes, serde_avro_bytes_opt, serde_avro_fixed, serde_avro_fixed_opt,
84 serde_avro_slice, serde_avro_slice_opt,
85 },
86};
87#[cfg(feature = "bzip")]
88pub use codec::bzip::Bzip2Settings;
89#[cfg(feature = "xz")]
90pub use codec::xz::XzSettings;
91#[cfg(feature = "zstandard")]
92pub use codec::zstandard::ZstandardSettings;
93pub use codec::{Codec, DeflateSettings};
94pub use decimal::Decimal;
95pub use duration::{Days, Duration, Millis, Months};
96pub use error::Error;
97#[expect(
98 deprecated,
99 reason = "Still need to export it until we remove it completely"
100)]
101pub use reader::{
102 Reader,
103 datum::{from_avro_datum, from_avro_datum_reader_schemata, from_avro_datum_schemata},
104 read_marker,
105 single_object::{GenericSingleObjectReader, SpecificSingleObjectReader},
106};
107pub use schema::Schema;
108pub use serde::{AvroSchema, AvroSchemaComponent, from_value, to_value};
109pub use uuid::Uuid;
110#[expect(
111 deprecated,
112 reason = "Still need to export it until we remove it completely"
113)]
114pub use writer::{
115 Clearable, Writer, WriterBuilder,
116 datum::{to_avro_datum, to_avro_datum_schemata, write_avro_datum_ref},
117 single_object::{GenericSingleObjectWriter, SpecificSingleObjectWriter},
118};
119
120#[cfg(feature = "derive")]
121pub use apache_avro_derive::AvroSchema;
122
123pub type AvroResult<T> = Result<T, Error>;
125
126#[deprecated(
136 since = "0.21.0",
137 note = "Please use apache_avro::util::max_allocation_bytes"
138)]
139pub fn max_allocation_bytes(num_bytes: usize) -> usize {
140 util::max_allocation_bytes(num_bytes)
141}
142
143#[deprecated(
156 since = "0.21.0",
157 note = "Please use apache_avro::util::set_serde_human_readable"
158)]
159pub fn set_serde_human_readable(human_readable: bool) -> bool {
160 util::set_serde_human_readable(human_readable)
161}
162
163#[cfg(test)]
164mod tests {
165 use crate::{
166 Codec, Reader, Schema, Writer,
167 reader::datum::GenericDatumReader,
168 types::{Record, Value},
169 };
170 use apache_avro_test_helper::TestResult;
171 use pretty_assertions::assert_eq;
172
173 #[test]
175 fn test_enum_default() {
176 let writer_raw_schema = r#"
177 {
178 "type": "record",
179 "name": "test",
180 "fields": [
181 {"name": "a", "type": "long", "default": 42},
182 {"name": "b", "type": "string"}
183 ]
184 }
185 "#;
186 let reader_raw_schema = r#"
187 {
188 "type": "record",
189 "name": "test",
190 "fields": [
191 {"name": "a", "type": "long", "default": 42},
192 {"name": "b", "type": "string"},
193 {
194 "name": "c",
195 "type": {
196 "type": "enum",
197 "name": "suit",
198 "symbols": ["diamonds", "spades", "clubs", "hearts"]
199 },
200 "default": "spades"
201 }
202 ]
203 }
204 "#;
205 let writer_schema = Schema::parse_str(writer_raw_schema).unwrap();
206 let reader_schema = Schema::parse_str(reader_raw_schema).unwrap();
207 let mut writer = Writer::with_codec(&writer_schema, Vec::new(), Codec::Null).unwrap();
208 let mut record = Record::new(writer.schema()).unwrap();
209 record.put("a", 27i64);
210 record.put("b", "foo");
211 writer.append_value(record).unwrap();
212 let input = writer.into_inner().unwrap();
213 let mut reader = Reader::builder(&input[..])
214 .reader_schema(&reader_schema)
215 .build()
216 .unwrap();
217 assert_eq!(
218 reader.next().unwrap().unwrap(),
219 Value::Record(vec![
220 ("a".to_string(), Value::Long(27)),
221 ("b".to_string(), Value::String("foo".to_string())),
222 ("c".to_string(), Value::Enum(1, "spades".to_string())),
223 ])
224 );
225 assert!(reader.next().is_none());
226 }
227
228 #[test]
230 fn test_enum_string_value() {
231 let raw_schema = r#"
232 {
233 "type": "record",
234 "name": "test",
235 "fields": [
236 {"name": "a", "type": "long", "default": 42},
237 {"name": "b", "type": "string"},
238 {
239 "name": "c",
240 "type": {
241 "type": "enum",
242 "name": "suit",
243 "symbols": ["diamonds", "spades", "clubs", "hearts"]
244 },
245 "default": "spades"
246 }
247 ]
248 }
249 "#;
250 let schema = Schema::parse_str(raw_schema).unwrap();
251 let mut writer = Writer::with_codec(&schema, Vec::new(), Codec::Null).unwrap();
252 let mut record = Record::new(writer.schema()).unwrap();
253 record.put("a", 27i64);
254 record.put("b", "foo");
255 record.put("c", "clubs");
256 writer.append_value(record).unwrap();
257 let input = writer.into_inner().unwrap();
258 let mut reader = Reader::builder(&input[..])
259 .reader_schema(&schema)
260 .build()
261 .unwrap();
262 assert_eq!(
263 reader.next().unwrap().unwrap(),
264 Value::Record(vec![
265 ("a".to_string(), Value::Long(27)),
266 ("b".to_string(), Value::String("foo".to_string())),
267 ("c".to_string(), Value::Enum(2, "clubs".to_string())),
268 ])
269 );
270 assert!(reader.next().is_none());
271 }
272
273 #[test]
275 fn test_enum_no_reader_schema() {
276 let writer_raw_schema = r#"
277 {
278 "type": "record",
279 "name": "test",
280 "fields": [
281 {"name": "a", "type": "long", "default": 42},
282 {"name": "b", "type": "string"},
283 {
284 "name": "c",
285 "type": {
286 "type": "enum",
287 "name": "suit",
288 "symbols": ["diamonds", "spades", "clubs", "hearts"]
289 },
290 "default": "spades"
291 }
292 ]
293 }
294 "#;
295 let writer_schema = Schema::parse_str(writer_raw_schema).unwrap();
296 let mut writer = Writer::with_codec(&writer_schema, Vec::new(), Codec::Null).unwrap();
297 let mut record = Record::new(writer.schema()).unwrap();
298 record.put("a", 27i64);
299 record.put("b", "foo");
300 record.put("c", "clubs");
301 writer.append_value(record).unwrap();
302 let input = writer.into_inner().unwrap();
303 let mut reader = Reader::new(&input[..]).unwrap();
304 assert_eq!(
305 reader.next().unwrap().unwrap(),
306 Value::Record(vec![
307 ("a".to_string(), Value::Long(27)),
308 ("b".to_string(), Value::String("foo".to_string())),
309 ("c".to_string(), Value::Enum(2, "clubs".to_string())),
310 ])
311 );
312 }
313
314 #[test]
315 fn test_illformed_length() -> TestResult {
316 let raw_schema = r#"
317 {
318 "type": "record",
319 "name": "test",
320 "fields": [
321 {"name": "a", "type": "long", "default": 42},
322 {"name": "b", "type": "string"}
323 ]
324 }
325 "#;
326
327 let schema = Schema::parse_str(raw_schema).unwrap();
328
329 let illformed: &[u8] = &[0x3e, 0x15, 0xff, 0x1f, 0x15, 0xff];
331
332 let value = GenericDatumReader::builder(&schema)
333 .build()?
334 .read_value(&mut &*illformed);
335 assert!(value.is_err());
336
337 Ok(())
338 }
339}