blob: 4128eef1a01f75c84eb183aeaef801af1ad9ead7 [file] [log] [blame]
/*
* 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
*
* https://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.
*/
#ifndef AVRO_CONSUMER_H
#define AVRO_CONSUMER_H
#ifdef __cplusplus
extern "C" {
#define CLOSE_EXTERN }
#else
#define CLOSE_EXTERN
#endif
#include <avro/platform.h>
#include <stdlib.h>
#include <avro/io.h>
#include <avro/schema.h>
/*---------------------------------------------------------------------
* Consumers
*/
/**
* A <i>consumer</i> is an object that knows how to process Avro data.
* There are consumer methods for each type of Avro data. The
* <code>avro_consumer_t</code> struct is an abstract superclass, which
* you don't instantiate directly. Later in this file, we define
* several consumer classes that know how to process Avro data in
* specific ways.
*
* For compound Avro values (records, arrays, maps, and unions), the
* consumer callbacks provide a nested consumer that should be used to
* process subvalues. Each consumer instance, including these
* "subconsumers", contains a reference to the schema of the data that
* it expects to process. This means that the functions that produce
* Avro data (such as avro_consume_binary) don't need to maintain their
* own references to any schemas, since they'll be encapsulated in the
* consumer that they pass their data off to.
*/
typedef struct avro_consumer_t avro_consumer_t;
struct avro_consumer_t {
/**
* The schema of the data that this consumer expects to process.
*/
avro_schema_t schema;
/**
* Called when this consumer is freed. This function should
* free any additional resources acquired by a consumer
* subclass.
*/
void (*free)(avro_consumer_t *consumer);
/* PRIMITIVE VALUES */
/**
* Called when a boolean value is encountered.
*/
int (*boolean_value)(avro_consumer_t *consumer,
int value,
void *user_data);
/**
* Called when a bytes value is encountered. The @ref value
* pointer is only guaranteed to be valid for the duration of
* the callback function. If you need to save the data for
* processing later, you must copy it into another buffer.
*/
int (*bytes_value)(avro_consumer_t *consumer,
const void *value, size_t value_len,
void *user_data);
/**
* Called when a double value is encountered.
*/
int (*double_value)(avro_consumer_t *consumer,
double value,
void *user_data);
/**
* Called when a float value is encountered.
*/
int (*float_value)(avro_consumer_t *consumer,
float value,
void *user_data);
/**
* Called when an int value is encountered.
*/
int (*int_value)(avro_consumer_t *consumer,
int32_t value,
void *user_data);
/**
* Called when a long value is encountered.
*/
int (*long_value)(avro_consumer_t *consumer,
int64_t value,
void *user_data);
/**
* Called when a null value is encountered.
*/
int (*null_value)(avro_consumer_t *consumer, void *user_data);
/**
* Called when a string value is encountered. The @ref value
* pointer will point at UTF-8 encoded data. (If the data
* you're representing isn't a UTF-8 Unicode string, you
* should use the bytes type.) The @ref value_len parameter
* gives the length of the data in bytes, not in Unicode
* characters. The @ref value pointer is only guaranteed to
* be valid for the duration of the callback function. If you
* need to save the data for processing later, you must copy
* it into another buffer.
*/
int (*string_value)(avro_consumer_t *consumer,
const void *value, size_t value_len,
void *user_data);
/* COMPOUND VALUES */
/**
* Called when the beginning of an array block is encountered.
* The @ref block_count parameter will contain the number of
* elements in this block.
*/
int (*array_start_block)(avro_consumer_t *consumer,
int is_first_block,
unsigned int block_count,
void *user_data);
/**
* Called before each individual element of an array is
* processed. The index of the current element is passed into
* the callback. The callback should fill in @ref
* element_consumer and @ref element_user_data with the consumer
* and <code>user_data</code> pointer to use to process the
* element.
*/
int (*array_element)(avro_consumer_t *consumer,
unsigned int index,
avro_consumer_t **element_consumer,
void **element_user_data,
void *user_data);
/**
* Called when an enum value is encountered.
*/
int (*enum_value)(avro_consumer_t *consumer, int value,
void *user_data);
/**
* Called when a fixed value is encountered. The @ref value
* pointer is only guaranteed to be valid for the duration of
* the callback function. If you need to save the data for
* processing later, you must copy it into another buffer.
*/
int (*fixed_value)(avro_consumer_t *consumer,
const void *value, size_t value_len,
void *user_data);
/**
* Called when the beginning of a map block is encountered.
* The @ref block_count parameter will contain the number of
* elements in this block.
*/
int (*map_start_block)(avro_consumer_t *consumer,
int is_first_block,
unsigned int block_count,
void *user_data);
/**
* Called before each individual element of a map is
* processed. The index and key of the current element is
* passed into the callback. The key is only guaranteed to be
* valid for the duration of the map_element_start callback,
* and the map's subschema callback. If you need to save it for
* later use, you must copy the key into another memory
* location. The callback should fill in @ref value_consumer
* and @ref value_user_data with the consumer and
* <code>user_data</code> pointer to use to process the value.
*/
int (*map_element)(avro_consumer_t *consumer,
unsigned int index,
const char *key,
avro_consumer_t **value_consumer,
void **value_user_data,
void *user_data);
/**
* Called when the beginning of a record is encountered.
*/
int (*record_start)(avro_consumer_t *consumer,
void *user_data);
/**
* Called before each individual field of a record is
* processed. The index and name of the current field is
* passed into the callback. The name is only guaranteed to
* be valid for the duration of the record_field_start
* callback, and the field's subschema callback. If you need to
* save it for later use, you must copy the key into another
* memory location. The callback should fill in @ref
* field_consumer and @ref field_user_data with the consumer
* <code>user_data</code> pointer to use to process the field.
*/
int (*record_field)(avro_consumer_t *consumer,
unsigned int index,
avro_consumer_t **field_consumer,
void **field_user_data,
void *user_data);
/**
* Called when a union value is encountered. The callback
* should fill in @ref branch_consumer and @ref branch_user_data
* with the consumer <code>user_data</code> pointer to use to
* process the branch.
*/
int (*union_branch)(avro_consumer_t *consumer,
unsigned int discriminant,
avro_consumer_t **branch_consumer,
void **branch_user_data,
void *user_data);
};
/**
* Calls the given callback in consumer, if it's present. If the
* callback is NULL, it just returns a success code.
*/
#define avro_consumer_call(consumer, callback, ...) \
(((consumer)->callback == NULL)? 0: \
(consumer)->callback((consumer), __VA_ARGS__))
/**
* Frees an @ref avro_consumer_t instance. (This function works on
* consumer subclasses, too.)
*/
void avro_consumer_free(avro_consumer_t *consumer);
/*---------------------------------------------------------------------
* Resolvers
*/
/**
* A <i>resolver</i> is a special kind of consumer that knows how to
* implement Avro's schema resolution rules to translate between a
* writer schema and a reader schema. The consumer callbacks line up
* with the writer schema; as each element of the datum is produced, the
* resolver fills in the contents of an @ref avro_datum_t instance.
* (The datum is provided as the user_data when you use the consumer.)
*/
avro_consumer_t *
avro_resolver_new(avro_schema_t writer_schema,
avro_schema_t reader_schema);
/*---------------------------------------------------------------------
* Binary encoding
*/
/**
* Reads an Avro datum from the given @ref avro_reader_t. As the
* datum is read, each portion of it is passed off to the appropriate
* callback in @ref consumer.
*/
int
avro_consume_binary(avro_reader_t reader,
avro_consumer_t *consumer,
void *ud);
CLOSE_EXTERN
#endif