1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to you under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  * https://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14  * implied.  See the License for the specific language governing
15  * permissions and limitations under the License.
16  */
17 
18 #include <avro/platform.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include "avro/allocation.h"
23 #include "avro/data.h"
24 #include "avro/errors.h"
25 #include "avro/generic.h"
26 #include "avro/refcount.h"
27 #include "avro/schema.h"
28 #include "avro/value.h"
29 #include "avro_generic_internal.h"
30 #include "avro_private.h"
31 
32 
33 /*-----------------------------------------------------------------------
34  * Forward definitions
35  */
36 
37 typedef struct avro_generic_link_value_iface  avro_generic_link_value_iface_t;
38 
39 typedef struct memoize_state_t {
40 	avro_memoize_t  mem;
41 	avro_generic_link_value_iface_t  *links;
42 } memoize_state_t;
43 
44 static avro_generic_value_iface_t *
45 avro_generic_class_from_schema_memoized(avro_schema_t schema,
46 					memoize_state_t *state);
47 
48 
49 /*-----------------------------------------------------------------------
50  * Generic support functions
51  */
52 
53 int
54 avro_generic_value_new(avro_value_iface_t *iface, avro_value_t *dest)
55 {
56 	int  rval;
57 	avro_generic_value_iface_t  *giface =
58 	    container_of(iface, avro_generic_value_iface_t, parent);
59 	size_t  instance_size = avro_value_instance_size(giface);
60 	void  *self = avro_malloc(instance_size + sizeof(volatile int));
61 	if (self == NULL) {
62 		avro_set_error(strerror(ENOMEM));
63 		dest->iface = NULL;
64 		dest->self = NULL;
65 		return ENOMEM;
66 	}
67 
68 	volatile int  *refcount = (volatile int *) self;
69 	self = (char *) self + sizeof(volatile int);
70 
71 	*refcount = 1;
72 	rval = avro_value_init(giface, self);
73 	if (rval != 0) {
74 		avro_free(self, instance_size);
75 		dest->iface = NULL;
76 		dest->self = NULL;
77 		return rval;
78 	}
79 
80 	dest->iface = avro_value_iface_incref(&giface->parent);
81 	dest->self = self;
82 	return 0;
83 }
84 
85 static void
86 avro_generic_value_free(const avro_value_iface_t *iface, void *self)
87 {
88 	if (self != NULL) {
89 		const avro_generic_value_iface_t  *giface =
90 		    container_of(iface, avro_generic_value_iface_t, parent);
91 		size_t  instance_size = avro_value_instance_size(giface);
92 		avro_value_done(giface, self);
93 		self = (char *) self - sizeof(volatile int);
94 		avro_free(self, instance_size + sizeof(volatile int));
95 	}
96 }
97 
98 static void
99 avro_generic_value_incref(avro_value_t *value)
100 {
101 	/*
102 	 * This only works if you pass in the top-level value.
103 	 */
104 
105 	volatile int  *refcount = (volatile int *) ((char *) value->self - sizeof(volatile int));
106 	avro_refcount_inc(refcount);
107 }
108 
109 static void
110 avro_generic_value_decref(avro_value_t *value)
111 {
112 	/*
113 	 * This only works if you pass in the top-level value.
114 	 */
115 
116 	volatile int  *refcount = (volatile int *) ((char *) value->self - sizeof(volatile int));
117 	if (avro_refcount_dec(refcount)) {
118 		avro_generic_value_free(value->iface, value->self);
119 	}
120 }
121 
122 
123 /*-----------------------------------------------------------------------
124  * Recursive schemas
125  */
126 
127 /*
128  * Recursive schemas are handled specially; the value implementation for
129  * an AVRO_LINK schema is simply a wrapper around the value
130  * implementation for the link's target schema.  The value methods all
131  * delegate to the wrapped implementation.
132  *
133  * We don't set the target_iface pointer when the link implementation is
134  * first created, since we might not have finished creating the
135  * implementation for the target schema.  (We create the implementations
136  * for child schemas depth-first, so the target schema's implementation
137  * won't be done until all of its descendants — including the link
138  * schema — have been instantiated.)
139  *
140  * So anyway, we set the target_iface pointer to NULL at first.  And
141  * then in a fix-up stage, once all of the non-link schemas have been
142  * instantiated, we go through and set the target_iface pointers for any
143  * link schemas we encountered.
144  */
145 
146 struct avro_generic_link_value_iface {
147 	avro_generic_value_iface_t  parent;
148 
149 	/** The reference count for this interface. */
150 	volatile int  refcount;
151 
152 	/** The schema for this interface. */
153 	avro_schema_t  schema;
154 
155 	/** The target's implementation. */
156 	avro_generic_value_iface_t  *target_giface;
157 
158 	/**
159 	 * A pointer to the “next” link interface that we've had to
160 	 * create.  We use this as we're creating the overall top-level
161 	 * value interface to keep track of which ones we have to fix up
162 	 * afterwards.
163 	 */
164 	avro_generic_link_value_iface_t  *next;
165 };
166 
167 
168 static avro_value_iface_t *
169 avro_generic_link_incref_iface(avro_value_iface_t *viface)
170 {
171 	avro_generic_link_value_iface_t  *iface =
172 	    container_of(viface, avro_generic_link_value_iface_t, parent);
173 	avro_refcount_inc(&iface->refcount);
174 	return viface;
175 }
176 
177 static void
178 avro_generic_link_decref_iface(avro_value_iface_t *viface)
179 {
180 	avro_generic_link_value_iface_t  *iface =
181 	    container_of(viface, avro_generic_link_value_iface_t, parent.parent);
182 
183 	if (avro_refcount_dec(&iface->refcount)) {
184 		/* We don't keep a reference to the target
185 		 * implementation, since that would give us a reference
186 		 * cycle. */
187 		/* We do however keep a reference to the target
188 		 * schema, which we need to decrement before freeing
189 		 * the link */
190 		avro_schema_decref(iface->schema);
191 		avro_freet(avro_generic_link_value_iface_t, iface);
192 	}
193 }
194 
195 
196 static int
197 avro_generic_link_reset(const avro_value_iface_t *iface, void *vself)
198 {
199 	AVRO_UNUSED(iface);
200 	avro_value_t  *self = (avro_value_t *) vself;
201 	return avro_value_reset(self);
202 }
203 
204 static avro_type_t
205 avro_generic_link_get_type(const avro_value_iface_t *viface, const void *vself)
206 {
207 	AVRO_UNUSED(viface);
208 	const avro_value_t  *self = (const avro_value_t *) vself;
209 	return avro_value_get_type(self);
210 }
211 
212 static avro_schema_t
213 avro_generic_link_get_schema(const avro_value_iface_t *viface, const void *vself)
214 {
215 	AVRO_UNUSED(viface);
216 	const avro_value_t  *self = (const avro_value_t *) vself;
217 	return avro_value_get_schema(self);
218 }
219 
220 static int
221 avro_generic_link_get_boolean(const avro_value_iface_t *iface,
222 			      const void *vself, int *out)
223 {
224 	AVRO_UNUSED(iface);
225 	const avro_value_t  *self = (const avro_value_t *) vself;
226 	return avro_value_get_boolean(self, out);
227 }
228 
229 static int
230 avro_generic_link_get_bytes(const avro_value_iface_t *iface,
231 			    const void *vself, const void **buf, size_t *size)
232 {
233 	AVRO_UNUSED(iface);
234 	const avro_value_t  *self = (const avro_value_t *) vself;
235 	return avro_value_get_bytes(self, buf, size);
236 }
237 
238 static int
239 avro_generic_link_grab_bytes(const avro_value_iface_t *iface,
240 			     const void *vself, avro_wrapped_buffer_t *dest)
241 {
242 	AVRO_UNUSED(iface);
243 	const avro_value_t  *self = (const avro_value_t *) vself;
244 	return avro_value_grab_bytes(self, dest);
245 }
246 
247 static int
248 avro_generic_link_get_double(const avro_value_iface_t *iface,
249 			     const void *vself, double *out)
250 {
251 	AVRO_UNUSED(iface);
252 	const avro_value_t  *self = (const avro_value_t *) vself;
253 	return avro_value_get_double(self, out);
254 }
255 
256 static int
257 avro_generic_link_get_float(const avro_value_iface_t *iface,
258 			    const void *vself, float *out)
259 {
260 	AVRO_UNUSED(iface);
261 	const avro_value_t  *self = (const avro_value_t *) vself;
262 	return avro_value_get_float(self, out);
263 }
264 
265 static int
266 avro_generic_link_get_int(const avro_value_iface_t *iface,
267 			  const void *vself, int32_t *out)
268 {
269 	AVRO_UNUSED(iface);
270 	const avro_value_t  *self = (const avro_value_t *) vself;
271 	return avro_value_get_int(self, out);
272 }
273 
274 static int
275 avro_generic_link_get_long(const avro_value_iface_t *iface,
276 			   const void *vself, int64_t *out)
277 {
278 	AVRO_UNUSED(iface);
279 	const avro_value_t  *self = (const avro_value_t *) vself;
280 	return avro_value_get_long(self, out);
281 }
282 
283 static int
284 avro_generic_link_get_null(const avro_value_iface_t *iface, const void *vself)
285 {
286 	AVRO_UNUSED(iface);
287 	const avro_value_t  *self = (const avro_value_t *) vself;
288 	return avro_value_get_null(self);
289 }
290 
291 static int
292 avro_generic_link_get_string(const avro_value_iface_t *iface,
293 			     const void *vself, const char **str, size_t *size)
294 {
295 	AVRO_UNUSED(iface);
296 	const avro_value_t  *self = (const avro_value_t *) vself;
297 	return avro_value_get_string(self, str, size);
298 }
299 
300 static int
301 avro_generic_link_grab_string(const avro_value_iface_t *iface,
302 			      const void *vself, avro_wrapped_buffer_t *dest)
303 {
304 	AVRO_UNUSED(iface);
305 	const avro_value_t  *self = (const avro_value_t *) vself;
306 	return avro_value_grab_string(self, dest);
307 }
308 
309 static int
310 avro_generic_link_get_enum(const avro_value_iface_t *iface,
311 			   const void *vself, int *out)
312 {
313 	AVRO_UNUSED(iface);
314 	const avro_value_t  *self = (const avro_value_t *) vself;
315 	return avro_value_get_enum(self, out);
316 }
317 
318 static int
319 avro_generic_link_get_fixed(const avro_value_iface_t *iface,
320 			    const void *vself, const void **buf, size_t *size)
321 {
322 	AVRO_UNUSED(iface);
323 	const avro_value_t  *self = (const avro_value_t *) vself;
324 	return avro_value_get_fixed(self, buf, size);
325 }
326 
327 static int
328 avro_generic_link_grab_fixed(const avro_value_iface_t *iface,
329 			     const void *vself, avro_wrapped_buffer_t *dest)
330 {
331 	AVRO_UNUSED(iface);
332 	const avro_value_t  *self = (const avro_value_t *) vself;
333 	return avro_value_grab_fixed(self, dest);
334 }
335 
336 static int
337 avro_generic_link_set_boolean(const avro_value_iface_t *iface,
338 			      void *vself, int val)
339 {
340 	AVRO_UNUSED(iface);
341 	avro_value_t  *self = (avro_value_t *) vself;
342 	return avro_value_set_boolean(self, val);
343 }
344 
345 static int
346 avro_generic_link_set_bytes(const avro_value_iface_t *iface,
347 			    void *vself, void *buf, size_t size)
348 {
349 	AVRO_UNUSED(iface);
350 	avro_value_t  *self = (avro_value_t *) vself;
351 	return avro_value_set_bytes(self, buf, size);
352 }
353 
354 static int
355 avro_generic_link_give_bytes(const avro_value_iface_t *iface,
356 			     void *vself, avro_wrapped_buffer_t *buf)
357 {
358 	AVRO_UNUSED(iface);
359 	avro_value_t  *self = (avro_value_t *) vself;
360 	return avro_value_give_bytes(self, buf);
361 }
362 
363 static int
364 avro_generic_link_set_double(const avro_value_iface_t *iface,
365 			     void *vself, double val)
366 {
367 	AVRO_UNUSED(iface);
368 	avro_value_t  *self = (avro_value_t *) vself;
369 	return avro_value_set_double(self, val);
370 }
371 
372 static int
373 avro_generic_link_set_float(const avro_value_iface_t *iface,
374 			    void *vself, float val)
375 {
376 	AVRO_UNUSED(iface);
377 	avro_value_t  *self = (avro_value_t *) vself;
378 	return avro_value_set_float(self, val);
379 }
380 
381 static int
382 avro_generic_link_set_int(const avro_value_iface_t *iface,
383 			  void *vself, int32_t val)
384 {
385 	AVRO_UNUSED(iface);
386 	avro_value_t  *self = (avro_value_t *) vself;
387 	return avro_value_set_int(self, val);
388 }
389 
390 static int
391 avro_generic_link_set_long(const avro_value_iface_t *iface,
392 			   void *vself, int64_t val)
393 {
394 	AVRO_UNUSED(iface);
395 	avro_value_t  *self = (avro_value_t *) vself;
396 	return avro_value_set_long(self, val);
397 }
398 
399 static int
400 avro_generic_link_set_null(const avro_value_iface_t *iface, void *vself)
401 {
402 	AVRO_UNUSED(iface);
403 	avro_value_t  *self = (avro_value_t *) vself;
404 	return avro_value_set_null(self);
405 }
406 
407 static int
408 avro_generic_link_set_string(const avro_value_iface_t *iface,
409 			     void *vself, const char *str)
410 {
411 	AVRO_UNUSED(iface);
412 	avro_value_t  *self = (avro_value_t *) vself;
413 	return avro_value_set_string(self, str);
414 }
415 
416 static int
417 avro_generic_link_set_string_len(const avro_value_iface_t *iface,
418 				 void *vself, const char *str, size_t size)
419 {
420 	AVRO_UNUSED(iface);
421 	avro_value_t  *self = (avro_value_t *) vself;
422 	return avro_value_set_string_len(self, str, size);
423 }
424 
425 static int
426 avro_generic_link_give_string_len(const avro_value_iface_t *iface,
427 				  void *vself, avro_wrapped_buffer_t *buf)
428 {
429 	AVRO_UNUSED(iface);
430 	avro_value_t  *self = (avro_value_t *) vself;
431 	return avro_value_give_string_len(self, buf);
432 }
433 
434 static int
435 avro_generic_link_set_enum(const avro_value_iface_t *iface,
436 			   void *vself, int val)
437 {
438 	AVRO_UNUSED(iface);
439 	avro_value_t  *self = (avro_value_t *) vself;
440 	return avro_value_set_enum(self, val);
441 }
442 
443 static int
444 avro_generic_link_set_fixed(const avro_value_iface_t *iface,
445 			    void *vself, void *buf, size_t size)
446 {
447 	AVRO_UNUSED(iface);
448 	avro_value_t  *self = (avro_value_t *) vself;
449 	return avro_value_set_fixed(self, buf, size);
450 }
451 
452 static int
453 avro_generic_link_give_fixed(const avro_value_iface_t *iface,
454 			     void *vself, avro_wrapped_buffer_t *buf)
455 {
456 	AVRO_UNUSED(iface);
457 	avro_value_t  *self = (avro_value_t *) vself;
458 	return avro_value_give_fixed(self, buf);
459 }
460 
461 static int
462 avro_generic_link_get_size(const avro_value_iface_t *iface,
463 			   const void *vself, size_t *size)
464 {
465 	AVRO_UNUSED(iface);
466 	const avro_value_t  *self = (const avro_value_t *) vself;
467 	return avro_value_get_size(self, size);
468 }
469 
470 static int
471 avro_generic_link_get_by_index(const avro_value_iface_t *iface,
472 			       const void *vself, size_t index,
473 			       avro_value_t *child, const char **name)
474 {
475 	AVRO_UNUSED(iface);
476 	const avro_value_t  *self = (const avro_value_t *) vself;
477 	return avro_value_get_by_index(self, index, child, name);
478 }
479 
480 static int
481 avro_generic_link_get_by_name(const avro_value_iface_t *iface,
482 			      const void *vself, const char *name,
483 			      avro_value_t *child, size_t *index)
484 {
485 	AVRO_UNUSED(iface);
486 	const avro_value_t  *self = (const avro_value_t *) vself;
487 	return avro_value_get_by_name(self, name, child, index);
488 }
489 
490 static int
491 avro_generic_link_get_discriminant(const avro_value_iface_t *iface,
492 				   const void *vself, int *out)
493 {
494 	AVRO_UNUSED(iface);
495 	const avro_value_t  *self = (const avro_value_t *) vself;
496 	return avro_value_get_discriminant(self, out);
497 }
498 
499 static int
500 avro_generic_link_get_current_branch(const avro_value_iface_t *iface,
501 				     const void *vself, avro_value_t *branch)
502 {
503 	AVRO_UNUSED(iface);
504 	const avro_value_t  *self = (const avro_value_t *) vself;
505 	return avro_value_get_current_branch(self, branch);
506 }
507 
508 static int
509 avro_generic_link_append(const avro_value_iface_t *iface,
510 			 void *vself, avro_value_t *child_out,
511 			 size_t *new_index)
512 {
513 	AVRO_UNUSED(iface);
514 	avro_value_t  *self = (avro_value_t *) vself;
515 	return avro_value_append(self, child_out, new_index);
516 }
517 
518 static int
519 avro_generic_link_add(const avro_value_iface_t *iface,
520 		      void *vself, const char *key,
521 		      avro_value_t *child, size_t *index, int *is_new)
522 {
523 	AVRO_UNUSED(iface);
524 	avro_value_t  *self = (avro_value_t *) vself;
525 	return avro_value_add(self, key, child, index, is_new);
526 }
527 
528 static int
529 avro_generic_link_set_branch(const avro_value_iface_t *iface,
530 			     void *vself, int discriminant,
531 			     avro_value_t *branch)
532 {
533 	AVRO_UNUSED(iface);
534 	avro_value_t  *self = (avro_value_t *) vself;
535 	return avro_value_set_branch(self, discriminant, branch);
536 }
537 
538 static size_t
539 avro_generic_link_instance_size(const avro_value_iface_t *viface)
540 {
541 	AVRO_UNUSED(viface);
542 	return sizeof(avro_value_t);
543 }
544 
545 static int
546 avro_generic_link_init(const avro_value_iface_t *viface, void *vself)
547 {
548 	int  rval;
549 
550 	avro_generic_link_value_iface_t  *iface =
551 	    container_of(viface, avro_generic_link_value_iface_t, parent.parent);
552 
553 	avro_value_t  *self = (avro_value_t *) vself;
554 	ssize_t  target_instance_size =
555 	    avro_value_instance_size(iface->target_giface);
556 	if (target_instance_size < 0) {
557 		return EINVAL;
558 	}
559 
560 	self->iface = &iface->target_giface->parent;
561 
562 	if (target_instance_size == 0) {
563 		self->self = NULL;
564 	} else {
565 		self->self = avro_malloc(target_instance_size);
566 		if (self->self == NULL) {
567 			return ENOMEM;
568 		}
569 	}
570 
571 	rval = avro_value_init(iface->target_giface, self->self);
572 	if (rval != 0) {
573 		avro_free(self->self, target_instance_size);
574 	}
575 	return rval;
576 }
577 
578 static void
579 avro_generic_link_done(const avro_value_iface_t *iface, void *vself)
580 {
581 	AVRO_UNUSED(iface);
582 	avro_value_t  *self = (avro_value_t *) vself;
583 	avro_generic_value_iface_t  *target_giface =
584 	    container_of(self->iface, avro_generic_value_iface_t, parent);
585 	size_t  target_instance_size = avro_value_instance_size(target_giface);
586 	avro_value_done(target_giface, self->self);
587 	avro_free(self->self, target_instance_size);
588 	self->iface = NULL;
589 	self->self = NULL;
590 }
591 
592 static avro_generic_value_iface_t  AVRO_GENERIC_LINK_CLASS =
593 {
594 	{
595 		/* "class" methods */
596 		avro_generic_link_incref_iface,
597 		avro_generic_link_decref_iface,
598 		/* general "instance" methods */
599 		avro_generic_value_incref,
600 		avro_generic_value_decref,
601 		avro_generic_link_reset,
602 		avro_generic_link_get_type,
603 		avro_generic_link_get_schema,
604 		/* primitive getters */
605 		avro_generic_link_get_boolean,
606 		avro_generic_link_get_bytes,
607 		avro_generic_link_grab_bytes,
608 		avro_generic_link_get_double,
609 		avro_generic_link_get_float,
610 		avro_generic_link_get_int,
611 		avro_generic_link_get_long,
612 		avro_generic_link_get_null,
613 		avro_generic_link_get_string,
614 		avro_generic_link_grab_string,
615 		avro_generic_link_get_enum,
616 		avro_generic_link_get_fixed,
617 		avro_generic_link_grab_fixed,
618 		/* primitive setters */
619 		avro_generic_link_set_boolean,
620 		avro_generic_link_set_bytes,
621 		avro_generic_link_give_bytes,
622 		avro_generic_link_set_double,
623 		avro_generic_link_set_float,
624 		avro_generic_link_set_int,
625 		avro_generic_link_set_long,
626 		avro_generic_link_set_null,
627 		avro_generic_link_set_string,
628 		avro_generic_link_set_string_len,
629 		avro_generic_link_give_string_len,
630 		avro_generic_link_set_enum,
631 		avro_generic_link_set_fixed,
632 		avro_generic_link_give_fixed,
633 		/* compound getters */
634 		avro_generic_link_get_size,
635 		avro_generic_link_get_by_index,
636 		avro_generic_link_get_by_name,
637 		avro_generic_link_get_discriminant,
638 		avro_generic_link_get_current_branch,
639 		/* compound setters */
640 		avro_generic_link_append,
641 		avro_generic_link_add,
642 		avro_generic_link_set_branch
643 	},
644 	avro_generic_link_instance_size,
645 	avro_generic_link_init,
646 	avro_generic_link_done
647 };
648 
649 static avro_generic_link_value_iface_t *
650 avro_generic_link_class(avro_schema_t schema)
651 {
652 	if (!is_avro_link(schema)) {
653 		avro_set_error("Expected link schema");
654 		return NULL;
655 	}
656 
657 	avro_generic_link_value_iface_t  *iface =
658 		(avro_generic_link_value_iface_t *) avro_new(avro_generic_link_value_iface_t);
659 	if (iface == NULL) {
660 		return NULL;
661 	}
662 
663 	iface->parent = AVRO_GENERIC_LINK_CLASS;
664 	iface->refcount = 1;
665 	iface->schema = avro_schema_incref(schema);
666 	iface->next = NULL;
667 	return iface;
668 }
669 
670 
671 /*-----------------------------------------------------------------------
672  * boolean
673  */
674 
675 static int
676 avro_generic_boolean_reset(const avro_value_iface_t *iface, void *vself)
677 {
678 	AVRO_UNUSED(iface);
679 	int  *self = (int *) vself;
680 	*self = 0;
681 	return 0;
682 }
683 
684 static avro_type_t
685 avro_generic_boolean_get_type(const avro_value_iface_t *iface, const void *vself)
686 {
687 	AVRO_UNUSED(iface);
688 	AVRO_UNUSED(vself);
689 	return AVRO_BOOLEAN;
690 }
691 
692 static avro_schema_t
693 avro_generic_boolean_get_schema(const avro_value_iface_t *iface, const void *vself)
694 {
695 	AVRO_UNUSED(iface);
696 	AVRO_UNUSED(vself);
697 	return avro_schema_boolean();
698 }
699 
700 static int
701 avro_generic_boolean_get(const avro_value_iface_t *iface,
702 			 const void *vself, int *out)
703 {
704 	AVRO_UNUSED(iface);
705 	const int  *self = (const int *) vself;
706 	*out = *self;
707 	return 0;
708 }
709 
710 static int
711 avro_generic_boolean_set(const avro_value_iface_t *iface,
712 			 void *vself, int val)
713 {
714 	AVRO_UNUSED(iface);
715 	int  *self = (int *) vself;
716 	*self = val;
717 	return 0;
718 }
719 
720 static size_t
721 avro_generic_boolean_instance_size(const avro_value_iface_t *iface)
722 {
723 	AVRO_UNUSED(iface);
724 	return sizeof(int);
725 }
726 
727 static int
728 avro_generic_boolean_init(const avro_value_iface_t *iface, void *vself)
729 {
730 	AVRO_UNUSED(iface);
731 	int  *self = (int *) vself;
732 	*self = 0;
733 	return 0;
734 }
735 
736 static void
737 avro_generic_boolean_done(const avro_value_iface_t *iface, void *vself)
738 {
739 	AVRO_UNUSED(iface);
740 	AVRO_UNUSED(vself);
741 }
742 
743 static avro_generic_value_iface_t  AVRO_GENERIC_BOOLEAN_CLASS =
744 {
745 	{
746 		/* "class" methods */
747 		NULL, /* incref_iface */
748 		NULL, /* decref_iface */
749 		/* general "instance" methods */
750 		avro_generic_value_incref,
751 		avro_generic_value_decref,
752 		avro_generic_boolean_reset,
753 		avro_generic_boolean_get_type,
754 		avro_generic_boolean_get_schema,
755 		/* primitive getters */
756 		avro_generic_boolean_get,
757 		NULL, /* get_bytes */
758 		NULL, /* grab_bytes */
759 		NULL, /* get_double */
760 		NULL, /* get_float */
761 		NULL, /* get_int */
762 		NULL, /* get_long */
763 		NULL, /* get_null */
764 		NULL, /* get_string */
765 		NULL, /* grab_string */
766 		NULL, /* get_enum */
767 		NULL, /* get_fixed */
768 		NULL, /* grab_fixed */
769 		/* primitive setters */
770 		avro_generic_boolean_set,
771 		NULL, /* set_bytes */
772 		NULL, /* give_bytes */
773 		NULL, /* set_double */
774 		NULL, /* set_float */
775 		NULL, /* set_int */
776 		NULL, /* set_long */
777 		NULL, /* set_null */
778 		NULL, /* set_string */
779 		NULL, /* set_string_length */
780 		NULL, /* give_string_length */
781 		NULL, /* set_enum */
782 		NULL, /* set_fixed */
783 		NULL, /* give_fixed */
784 		/* compound getters */
785 		NULL, /* get_size */
786 		NULL, /* get_by_index */
787 		NULL, /* get_by_name */
788 		NULL, /* get_discriminant */
789 		NULL, /* get_current_branch */
790 		/* compound setters */
791 		NULL, /* append */
792 		NULL, /* add */
793 		NULL  /* set_branch */
794 	},
795 	avro_generic_boolean_instance_size,
796 	avro_generic_boolean_init,
797 	avro_generic_boolean_done
798 };
799 
800 avro_value_iface_t *
801 avro_generic_boolean_class(void)
802 {
803 	return &AVRO_GENERIC_BOOLEAN_CLASS.parent;
804 }
805 
806 int
807 avro_generic_boolean_new(avro_value_t *value, int val)
808 {
809 	int  rval;
810 	check(rval, avro_generic_value_new(&AVRO_GENERIC_BOOLEAN_CLASS.parent, value));
811 	return avro_generic_boolean_set(value->iface, value->self, val);
812 }
813 
814 /*-----------------------------------------------------------------------
815  * bytes
816  */
817 
818 static int
819 avro_generic_bytes_reset(const avro_value_iface_t *iface, void *vself)
820 {
821 	AVRO_UNUSED(iface);
822 	avro_raw_string_t  *self = (avro_raw_string_t *) vself;
823 	avro_raw_string_clear(self);
824 	return 0;
825 }
826 
827 static avro_type_t
828 avro_generic_bytes_get_type(const avro_value_iface_t *iface, const void *vself)
829 {
830 	AVRO_UNUSED(iface);
831 	AVRO_UNUSED(vself);
832 	return AVRO_BYTES;
833 }
834 
835 static avro_schema_t
836 avro_generic_bytes_get_schema(const avro_value_iface_t *iface, const void *vself)
837 {
838 	AVRO_UNUSED(iface);
839 	AVRO_UNUSED(vself);
840 	return avro_schema_bytes();
841 }
842 
843 static int
844 avro_generic_bytes_get(const avro_value_iface_t *iface,
845 		       const void *vself, const void **buf, size_t *size)
846 {
847 	AVRO_UNUSED(iface);
848 	const avro_raw_string_t  *self = (const avro_raw_string_t *) vself;
849 	if (buf != NULL) {
850 		*buf = avro_raw_string_get(self);
851 	}
852 	if (size != NULL) {
853 		*size = avro_raw_string_length(self);
854 	}
855 	return 0;
856 }
857 
858 static int
859 avro_generic_bytes_grab(const avro_value_iface_t *iface,
860 			const void *vself, avro_wrapped_buffer_t *dest)
861 {
862 	AVRO_UNUSED(iface);
863 	const avro_raw_string_t  *self = (const avro_raw_string_t *) vself;
864 	return avro_raw_string_grab(self, dest);
865 }
866 
867 static int
868 avro_generic_bytes_set(const avro_value_iface_t *iface,
869 		       void *vself, void *buf, size_t size)
870 {
871 	AVRO_UNUSED(iface);
872 	check_param(EINVAL, buf != NULL, "bytes contents");
873 	avro_raw_string_t  *self = (avro_raw_string_t *) vself;
874 	avro_raw_string_set_length(self, buf, size);
875 	return 0;
876 }
877 
878 static int
879 avro_generic_bytes_give(const avro_value_iface_t *iface,
880 			void *vself, avro_wrapped_buffer_t *buf)
881 {
882 	AVRO_UNUSED(iface);
883 	avro_raw_string_t  *self = (avro_raw_string_t *) vself;
884 	avro_raw_string_give(self, buf);
885 	return 0;
886 }
887 
888 static size_t
889 avro_generic_bytes_instance_size(const avro_value_iface_t *iface)
890 {
891 	AVRO_UNUSED(iface);
892 	return sizeof(avro_raw_string_t);
893 }
894 
895 static int
896 avro_generic_bytes_init(const avro_value_iface_t *iface, void *vself)
897 {
898 	AVRO_UNUSED(iface);
899 	avro_raw_string_t  *self = (avro_raw_string_t *) vself;
900 	avro_raw_string_init(self);
901 	return 0;
902 }
903 
904 static void
905 avro_generic_bytes_done(const avro_value_iface_t *iface, void *vself)
906 {
907 	AVRO_UNUSED(iface);
908 	avro_raw_string_t  *self = (avro_raw_string_t *) vself;
909 	avro_raw_string_done(self);
910 }
911 
912 static avro_generic_value_iface_t  AVRO_GENERIC_BYTES_CLASS =
913 {
914 	{
915 		/* "class" methods */
916 		NULL, /* incref_iface */
917 		NULL, /* decref_iface */
918 		/* general "instance" methods */
919 		avro_generic_value_incref,
920 		avro_generic_value_decref,
921 		avro_generic_bytes_reset,
922 		avro_generic_bytes_get_type,
923 		avro_generic_bytes_get_schema,
924 		/* primitive getters */
925 		NULL, /* get_boolean */
926 		avro_generic_bytes_get,
927 		avro_generic_bytes_grab,
928 		NULL, /* get_double */
929 		NULL, /* get_float */
930 		NULL, /* get_int */
931 		NULL, /* get_long */
932 		NULL, /* get_null */
933 		NULL, /* get_string */
934 		NULL, /* grab_string */
935 		NULL, /* get_enum */
936 		NULL, /* get_fixed */
937 		NULL, /* grab_fixed */
938 		/* primitive setters */
939 		NULL, /* set_boolean */
940 		avro_generic_bytes_set,
941 		avro_generic_bytes_give,
942 		NULL, /* set_double */
943 		NULL, /* set_float */
944 		NULL, /* set_int */
945 		NULL, /* set_long */
946 		NULL, /* set_null */
947 		NULL, /* set_string */
948 		NULL, /* set_string_length */
949 		NULL, /* give_string_length */
950 		NULL, /* set_enum */
951 		NULL, /* set_fixed */
952 		NULL, /* give_fixed */
953 		/* compound getters */
954 		NULL, /* get_size */
955 		NULL, /* get_by_index */
956 		NULL, /* get_by_name */
957 		NULL, /* get_discriminant */
958 		NULL, /* get_current_branch */
959 		/* compound setters */
960 		NULL, /* append */
961 		NULL, /* add */
962 		NULL  /* set_branch */
963 	},
964 	avro_generic_bytes_instance_size,
965 	avro_generic_bytes_init,
966 	avro_generic_bytes_done
967 };
968 
969 avro_value_iface_t *
970 avro_generic_bytes_class(void)
971 {
972 	return &AVRO_GENERIC_BYTES_CLASS.parent;
973 }
974 
975 int
976 avro_generic_bytes_new(avro_value_t *value, void *buf, size_t size)
977 {
978 	int  rval;
979 	check(rval, avro_generic_value_new(&AVRO_GENERIC_BYTES_CLASS.parent, value));
980 	return avro_generic_bytes_set(value->iface, value->self, buf, size);
981 }
982 
983 /*-----------------------------------------------------------------------
984  * double
985  */
986 
987 static int
988 avro_generic_double_reset(const avro_value_iface_t *iface, void *vself)
989 {
990 	AVRO_UNUSED(iface);
991 	double  *self = (double *) vself;
992 	*self = 0.0;
993 	return 0;
994 }
995 
996 static avro_type_t
997 avro_generic_double_get_type(const avro_value_iface_t *iface, const void *vself)
998 {
999 	AVRO_UNUSED(iface);
1000 	AVRO_UNUSED(vself);
1001 	return AVRO_DOUBLE;
1002 }
1003 
1004 static avro_schema_t
1005 avro_generic_double_get_schema(const avro_value_iface_t *iface, const void *vself)
1006 {
1007 	AVRO_UNUSED(iface);
1008 	AVRO_UNUSED(vself);
1009 	return avro_schema_double();
1010 }
1011 
1012 static int
1013 avro_generic_double_get(const avro_value_iface_t *iface,
1014 			const void *vself, double *out)
1015 {
1016 	AVRO_UNUSED(iface);
1017 	const double  *self = (const double *) vself;
1018 	*out = *self;
1019 	return 0;
1020 }
1021 
1022 static int
1023 avro_generic_double_set(const avro_value_iface_t *iface,
1024 			void *vself, double val)
1025 {
1026 	AVRO_UNUSED(iface);
1027 	double  *self = (double *) vself;
1028 	*self = val;
1029 	return 0;
1030 }
1031 
1032 static size_t
1033 avro_generic_double_instance_size(const avro_value_iface_t *iface)
1034 {
1035 	AVRO_UNUSED(iface);
1036 	return sizeof(double);
1037 }
1038 
1039 static int
1040 avro_generic_double_init(const avro_value_iface_t *iface, void *vself)
1041 {
1042 	AVRO_UNUSED(iface);
1043 	double  *self = (double *) vself;
1044 	*self = 0.0;
1045 	return 0;
1046 }
1047 
1048 static void
1049 avro_generic_double_done(const avro_value_iface_t *iface, void *vself)
1050 {
1051 	AVRO_UNUSED(iface);
1052 	AVRO_UNUSED(vself);
1053 }
1054 
1055 static avro_generic_value_iface_t  AVRO_GENERIC_DOUBLE_CLASS =
1056 {
1057 	{
1058 		/* "class" methods */
1059 		NULL, /* incref_iface */
1060 		NULL, /* decref_iface */
1061 		/* general "instance" methods */
1062 		avro_generic_value_incref,
1063 		avro_generic_value_decref,
1064 		avro_generic_double_reset,
1065 		avro_generic_double_get_type,
1066 		avro_generic_double_get_schema,
1067 		/* primitive getters */
1068 		NULL, /* get_boolean */
1069 		NULL, /* get_bytes */
1070 		NULL, /* grab_bytes */
1071 		avro_generic_double_get,
1072 		NULL, /* get_float */
1073 		NULL, /* get_int */
1074 		NULL, /* get_long */
1075 		NULL, /* get_null */
1076 		NULL, /* get_string */
1077 		NULL, /* grab_string */
1078 		NULL, /* get_enum */
1079 		NULL, /* get_fixed */
1080 		NULL, /* grab_fixed */
1081 		/* primitive setters */
1082 		NULL, /* set_boolean */
1083 		NULL, /* set_bytes */
1084 		NULL, /* give_bytes */
1085 		avro_generic_double_set,
1086 		NULL, /* set_float */
1087 		NULL, /* set_int */
1088 		NULL, /* set_long */
1089 		NULL, /* set_null */
1090 		NULL, /* set_string */
1091 		NULL, /* set_string_length */
1092 		NULL, /* give_string_length */
1093 		NULL, /* set_enum */
1094 		NULL, /* set_fixed */
1095 		NULL, /* give_fixed */
1096 		/* compound getters */
1097 		NULL, /* get_size */
1098 		NULL, /* get_by_index */
1099 		NULL, /* get_by_name */
1100 		NULL, /* get_discriminant */
1101 		NULL, /* get_current_branch */
1102 		/* compound setters */
1103 		NULL, /* append */
1104 		NULL, /* add */
1105 		NULL  /* set_branch */
1106 	},
1107 	avro_generic_double_instance_size,
1108 	avro_generic_double_init,
1109 	avro_generic_double_done
1110 };
1111 
1112 avro_value_iface_t *
1113 avro_generic_double_class(void)
1114 {
1115 	return &AVRO_GENERIC_DOUBLE_CLASS.parent;
1116 }
1117 
1118 int
1119 avro_generic_double_new(avro_value_t *value, double val)
1120 {
1121 	int  rval;
1122 	check(rval, avro_generic_value_new(&AVRO_GENERIC_DOUBLE_CLASS.parent, value));
1123 	return avro_generic_double_set(value->iface, value->self, val);
1124 }
1125 
1126 /*-----------------------------------------------------------------------
1127  * float
1128  */
1129 
1130 static int
1131 avro_generic_float_reset(const avro_value_iface_t *iface, void *vself)
1132 {
1133 	AVRO_UNUSED(iface);
1134 	float  *self = (float *) vself;
1135 	*self = 0.0f;
1136 	return 0;
1137 }
1138 
1139 static avro_type_t
1140 avro_generic_float_get_type(const avro_value_iface_t *iface, const void *vself)
1141 {
1142 	AVRO_UNUSED(iface);
1143 	AVRO_UNUSED(vself);
1144 	return AVRO_FLOAT;
1145 }
1146 
1147 static avro_schema_t
1148 avro_generic_float_get_schema(const avro_value_iface_t *iface, const void *vself)
1149 {
1150 	AVRO_UNUSED(iface);
1151 	AVRO_UNUSED(vself);
1152 	return avro_schema_float();
1153 }
1154 
1155 static int
1156 avro_generic_float_get(const avro_value_iface_t *iface,
1157 		       const void *vself, float *out)
1158 {
1159 	AVRO_UNUSED(iface);
1160 	const float  *self = (const float *) vself;
1161 	*out = *self;
1162 	return 0;
1163 }
1164 
1165 static int
1166 avro_generic_float_set(const avro_value_iface_t *iface,
1167 		       void *vself, float val)
1168 {
1169 	AVRO_UNUSED(iface);
1170 	float  *self = (float *) vself;
1171 	*self = val;
1172 	return 0;
1173 }
1174 
1175 static size_t
1176 avro_generic_float_instance_size(const avro_value_iface_t *iface)
1177 {
1178 	AVRO_UNUSED(iface);
1179 	return sizeof(float);
1180 }
1181 
1182 static int
1183 avro_generic_float_init(const avro_value_iface_t *iface, void *vself)
1184 {
1185 	AVRO_UNUSED(iface);
1186 	float  *self = (float *) vself;
1187 	*self = 0.0f;
1188 	return 0;
1189 }
1190 
1191 static void
1192 avro_generic_float_done(const avro_value_iface_t *iface, void *vself)
1193 {
1194 	AVRO_UNUSED(iface);
1195 	AVRO_UNUSED(vself);
1196 }
1197 
1198 static avro_generic_value_iface_t  AVRO_GENERIC_FLOAT_CLASS =
1199 {
1200 	{
1201 		/* "class" methods */
1202 		NULL, /* incref_iface */
1203 		NULL, /* decref_iface */
1204 		/* general "instance" methods */
1205 		avro_generic_value_incref,
1206 		avro_generic_value_decref,
1207 		avro_generic_float_reset,
1208 		avro_generic_float_get_type,
1209 		avro_generic_float_get_schema,
1210 		/* primitive getters */
1211 		NULL, /* get_boolean */
1212 		NULL, /* get_bytes */
1213 		NULL, /* grab_bytes */
1214 		NULL, /* get_double */
1215 		avro_generic_float_get,
1216 		NULL, /* get_int */
1217 		NULL, /* get_long */
1218 		NULL, /* get_null */
1219 		NULL, /* get_string */
1220 		NULL, /* grab_string */
1221 		NULL, /* get_enum */
1222 		NULL, /* get_fixed */
1223 		NULL, /* grab_fixed */
1224 		/* primitive setters */
1225 		NULL, /* set_boolean */
1226 		NULL, /* set_bytes */
1227 		NULL, /* give_bytes */
1228 		NULL, /* set_double */
1229 		avro_generic_float_set,
1230 		NULL, /* set_int */
1231 		NULL, /* set_long */
1232 		NULL, /* set_null */
1233 		NULL, /* set_string */
1234 		NULL, /* set_string_length */
1235 		NULL, /* give_string_length */
1236 		NULL, /* set_enum */
1237 		NULL, /* set_fixed */
1238 		NULL, /* give_fixed */
1239 		/* compound getters */
1240 		NULL, /* get_size */
1241 		NULL, /* get_by_index */
1242 		NULL, /* get_by_name */
1243 		NULL, /* get_discriminant */
1244 		NULL, /* get_current_branch */
1245 		/* compound setters */
1246 		NULL, /* append */
1247 		NULL, /* add */
1248 		NULL  /* set_branch */
1249 	},
1250 	avro_generic_float_instance_size,
1251 	avro_generic_float_init,
1252 	avro_generic_float_done
1253 };
1254 
1255 avro_value_iface_t *
1256 avro_generic_float_class(void)
1257 {
1258 	return &AVRO_GENERIC_FLOAT_CLASS.parent;
1259 }
1260 
1261 int
1262 avro_generic_float_new(avro_value_t *value, float val)
1263 {
1264 	int  rval;
1265 	check(rval, avro_generic_value_new(&AVRO_GENERIC_FLOAT_CLASS.parent, value));
1266 	return avro_generic_float_set(value->iface, value->self, val);
1267 }
1268 
1269 /*-----------------------------------------------------------------------
1270  * int
1271  */
1272 
1273 static int
1274 avro_generic_int_reset(const avro_value_iface_t *iface, void *vself)
1275 {
1276 	AVRO_UNUSED(iface);
1277 	int32_t  *self = (int32_t *) vself;
1278 	*self = 0;
1279 	return 0;
1280 }
1281 
1282 static avro_type_t
1283 avro_generic_int_get_type(const avro_value_iface_t *iface, const void *vself)
1284 {
1285 	AVRO_UNUSED(iface);
1286 	AVRO_UNUSED(vself);
1287 	return AVRO_INT32;
1288 }
1289 
1290 static avro_schema_t
1291 avro_generic_int_get_schema(const avro_value_iface_t *iface, const void *vself)
1292 {
1293 	AVRO_UNUSED(iface);
1294 	AVRO_UNUSED(vself);
1295 	return avro_schema_int();
1296 }
1297 
1298 static int
1299 avro_generic_int_get(const avro_value_iface_t *iface,
1300 		     const void *vself, int32_t *out)
1301 {
1302 	AVRO_UNUSED(iface);
1303 	const int32_t  *self = (const int32_t *) vself;
1304 	*out = *self;
1305 	return 0;
1306 }
1307 
1308 static int
1309 avro_generic_int_set(const avro_value_iface_t *iface,
1310 		     void *vself, int32_t val)
1311 {
1312 	AVRO_UNUSED(iface);
1313 	int32_t  *self = (int32_t *) vself;
1314 	*self = val;
1315 	return 0;
1316 }
1317 
1318 static size_t
1319 avro_generic_int_instance_size(const avro_value_iface_t *iface)
1320 {
1321 	AVRO_UNUSED(iface);
1322 	return sizeof(int32_t);
1323 }
1324 
1325 static int
1326 avro_generic_int_init(const avro_value_iface_t *iface, void *vself)
1327 {
1328 	AVRO_UNUSED(iface);
1329 	int32_t  *self = (int32_t *) vself;
1330 	*self = 0;
1331 	return 0;
1332 }
1333 
1334 static void
1335 avro_generic_int_done(const avro_value_iface_t *iface, void *vself)
1336 {
1337 	AVRO_UNUSED(iface);
1338 	AVRO_UNUSED(vself);
1339 }
1340 
1341 static avro_generic_value_iface_t  AVRO_GENERIC_INT_CLASS =
1342 {
1343 	{
1344 		/* "class" methods */
1345 		NULL, /* incref_iface */
1346 		NULL, /* decref_iface */
1347 		/* general "instance" methods */
1348 		avro_generic_value_incref,
1349 		avro_generic_value_decref,
1350 		avro_generic_int_reset,
1351 		avro_generic_int_get_type,
1352 		avro_generic_int_get_schema,
1353 		/* primitive getters */
1354 		NULL, /* get_boolean */
1355 		NULL, /* get_bytes */
1356 		NULL, /* grab_bytes */
1357 		NULL, /* get_double */
1358 		NULL, /* get_float */
1359 		avro_generic_int_get,
1360 		NULL, /* get_long */
1361 		NULL, /* get_null */
1362 		NULL, /* get_string */
1363 		NULL, /* grab_string */
1364 		NULL, /* get_enum */
1365 		NULL, /* get_fixed */
1366 		NULL, /* grab_fixed */
1367 		/* primitive setters */
1368 		NULL, /* set_boolean */
1369 		NULL, /* set_bytes */
1370 		NULL, /* give_bytes */
1371 		NULL, /* set_double */
1372 		NULL, /* set_float */
1373 		avro_generic_int_set,
1374 		NULL, /* set_long */
1375 		NULL, /* set_null */
1376 		NULL, /* set_string */
1377 		NULL, /* set_string_length */
1378 		NULL, /* give_string_length */
1379 		NULL, /* set_enum */
1380 		NULL, /* set_fixed */
1381 		NULL, /* give_fixed */
1382 		/* compound getters */
1383 		NULL, /* get_size */
1384 		NULL, /* get_by_index */
1385 		NULL, /* get_by_name */
1386 		NULL, /* get_discriminant */
1387 		NULL, /* get_current_branch */
1388 		/* compound setters */
1389 		NULL, /* append */
1390 		NULL, /* add */
1391 		NULL  /* set_branch */
1392 	},
1393 	avro_generic_int_instance_size,
1394 	avro_generic_int_init,
1395 	avro_generic_int_done
1396 };
1397 
1398 avro_value_iface_t *
1399 avro_generic_int_class(void)
1400 {
1401 	return &AVRO_GENERIC_INT_CLASS.parent;
1402 }
1403 
1404 int
1405 avro_generic_int_new(avro_value_t *value, int32_t val)
1406 {
1407 	int  rval;
1408 	check(rval, avro_generic_value_new(&AVRO_GENERIC_INT_CLASS.parent, value));
1409 	return avro_generic_int_set(value->iface, value->self, val);
1410 }
1411 
1412 /*-----------------------------------------------------------------------
1413  * long
1414  */
1415 
1416 static int
1417 avro_generic_long_reset(const avro_value_iface_t *iface, void *vself)
1418 {
1419 	AVRO_UNUSED(iface);
1420 	int64_t  *self = (int64_t *) vself;
1421 	*self = 0;
1422 	return 0;
1423 }
1424 
1425 static avro_type_t
1426 avro_generic_long_get_type(const avro_value_iface_t *iface, const void *vself)
1427 {
1428 	AVRO_UNUSED(iface);
1429 	AVRO_UNUSED(vself);
1430 	return AVRO_INT64;
1431 }
1432 
1433 static avro_schema_t
1434 avro_generic_long_get_schema(const avro_value_iface_t *iface, const void *vself)
1435 {
1436 	AVRO_UNUSED(iface);
1437 	AVRO_UNUSED(vself);
1438 	return avro_schema_long();
1439 }
1440 
1441 static int
1442 avro_generic_long_get(const avro_value_iface_t *iface,
1443 		      const void *vself, int64_t *out)
1444 {
1445 	AVRO_UNUSED(iface);
1446 	const int64_t  *self = (const int64_t *) vself;
1447 	*out = *self;
1448 	return 0;
1449 }
1450 
1451 static int
1452 avro_generic_long_set(const avro_value_iface_t *iface,
1453 		      void *vself, int64_t val)
1454 {
1455 	AVRO_UNUSED(iface);
1456 	int64_t  *self = (int64_t *) vself;
1457 	*self = val;
1458 	return 0;
1459 }
1460 
1461 static size_t
1462 avro_generic_long_instance_size(const avro_value_iface_t *iface)
1463 {
1464 	AVRO_UNUSED(iface);
1465 	return sizeof(int64_t);
1466 }
1467 
1468 static int
1469 avro_generic_long_init(const avro_value_iface_t *iface, void *vself)
1470 {
1471 	AVRO_UNUSED(iface);
1472 	int64_t  *self = (int64_t *) vself;
1473 	*self = 0;
1474 	return 0;
1475 }
1476 
1477 static void
1478 avro_generic_long_done(const avro_value_iface_t *iface, void *vself)
1479 {
1480 	AVRO_UNUSED(iface);
1481 	AVRO_UNUSED(vself);
1482 }
1483 
1484 static avro_generic_value_iface_t  AVRO_GENERIC_LONG_CLASS =
1485 {
1486 	{
1487 		/* "class" methods */
1488 		NULL, /* incref_iface */
1489 		NULL, /* decref_iface */
1490 		/* general "instance" methods */
1491 		avro_generic_value_incref,
1492 		avro_generic_value_decref,
1493 		avro_generic_long_reset,
1494 		avro_generic_long_get_type,
1495 		avro_generic_long_get_schema,
1496 		/* primitive getters */
1497 		NULL, /* get_boolean */
1498 		NULL, /* get_bytes */
1499 		NULL, /* grab_bytes */
1500 		NULL, /* get_double */
1501 		NULL, /* get_float */
1502 		NULL, /* get_int */
1503 		avro_generic_long_get,
1504 		NULL, /* get_null */
1505 		NULL, /* get_string */
1506 		NULL, /* grab_string */
1507 		NULL, /* get_enum */
1508 		NULL, /* get_fixed */
1509 		NULL, /* grab_fixed */
1510 		/* primitive setters */
1511 		NULL, /* set_boolean */
1512 		NULL, /* set_bytes */
1513 		NULL, /* give_bytes */
1514 		NULL, /* set_double */
1515 		NULL, /* set_float */
1516 		NULL, /* set_int */
1517 		avro_generic_long_set,
1518 		NULL, /* set_null */
1519 		NULL, /* set_string */
1520 		NULL, /* set_string_length */
1521 		NULL, /* give_string_length */
1522 		NULL, /* set_enum */
1523 		NULL, /* set_fixed */
1524 		NULL, /* give_fixed */
1525 		/* compound getters */
1526 		NULL, /* get_size */
1527 		NULL, /* get_by_index */
1528 		NULL, /* get_by_name */
1529 		NULL, /* get_discriminant */
1530 		NULL, /* get_current_branch */
1531 		/* compound setters */
1532 		NULL, /* append */
1533 		NULL, /* add */
1534 		NULL  /* set_branch */
1535 	},
1536 	avro_generic_long_instance_size,
1537 	avro_generic_long_init,
1538 	avro_generic_long_done
1539 };
1540 
1541 avro_value_iface_t *
1542 avro_generic_long_class(void)
1543 {
1544 	return &AVRO_GENERIC_LONG_CLASS.parent;
1545 }
1546 
1547 int
1548 avro_generic_long_new(avro_value_t *value, int64_t val)
1549 {
1550 	int  rval;
1551 	check(rval, avro_generic_value_new(&AVRO_GENERIC_LONG_CLASS.parent, value));
1552 	return avro_generic_long_set(value->iface, value->self, val);
1553 }
1554 
1555 /*-----------------------------------------------------------------------
1556  * null
1557  */
1558 
1559 static int
1560 avro_generic_null_reset(const avro_value_iface_t *iface, void *vself)
1561 {
1562 	AVRO_UNUSED(iface);
1563 	int  *self = (int *) vself;
1564 	*self = 0;
1565 	return 0;
1566 }
1567 
1568 static avro_type_t
1569 avro_generic_null_get_type(const avro_value_iface_t *iface, const void *vself)
1570 {
1571 	AVRO_UNUSED(iface);
1572 	AVRO_UNUSED(vself);
1573 	return AVRO_NULL;
1574 }
1575 
1576 static avro_schema_t
1577 avro_generic_null_get_schema(const avro_value_iface_t *iface, const void *vself)
1578 {
1579 	AVRO_UNUSED(iface);
1580 	AVRO_UNUSED(vself);
1581 	return avro_schema_null();
1582 }
1583 
1584 static int
1585 avro_generic_null_get(const avro_value_iface_t *iface, const void *vself)
1586 {
1587 	AVRO_UNUSED(iface);
1588 	AVRO_UNUSED(vself);
1589 	return 0;
1590 }
1591 
1592 static int
1593 avro_generic_null_set(const avro_value_iface_t *iface, void *vself)
1594 {
1595 	AVRO_UNUSED(iface);
1596 	AVRO_UNUSED(vself);
1597 	return 0;
1598 }
1599 
1600 static size_t
1601 avro_generic_null_instance_size(const avro_value_iface_t *iface)
1602 {
1603 	AVRO_UNUSED(iface);
1604 	return sizeof(int);
1605 }
1606 
1607 static int
1608 avro_generic_null_init(const avro_value_iface_t *iface, void *vself)
1609 {
1610 	AVRO_UNUSED(iface);
1611 	int  *self = (int *) vself;
1612 	*self = 0;
1613 	return 0;
1614 }
1615 
1616 static void
1617 avro_generic_null_done(const avro_value_iface_t *iface, void *vself)
1618 {
1619 	AVRO_UNUSED(iface);
1620 	AVRO_UNUSED(vself);
1621 }
1622 
1623 static avro_generic_value_iface_t  AVRO_GENERIC_NULL_CLASS =
1624 {
1625 	{
1626 		/* "class" methods */
1627 		NULL, /* incref_iface */
1628 		NULL, /* decref_iface */
1629 		/* general "instance" methods */
1630 		avro_generic_value_incref,
1631 		avro_generic_value_decref,
1632 		avro_generic_null_reset,
1633 		avro_generic_null_get_type,
1634 		avro_generic_null_get_schema,
1635 		/* primitive getters */
1636 		NULL, /* get_boolean */
1637 		NULL, /* get_bytes */
1638 		NULL, /* grab_bytes */
1639 		NULL, /* get_double */
1640 		NULL, /* get_float */
1641 		NULL, /* get_int */
1642 		NULL, /* get_long */
1643 		avro_generic_null_get,
1644 		NULL, /* get_string */
1645 		NULL, /* grab_string */
1646 		NULL, /* get_enum */
1647 		NULL, /* get_fixed */
1648 		NULL, /* grab_fixed */
1649 		/* primitive setters */
1650 		NULL, /* set_boolean */
1651 		NULL, /* set_bytes */
1652 		NULL, /* give_bytes */
1653 		NULL, /* set_double */
1654 		NULL, /* set_float */
1655 		NULL, /* set_int */
1656 		NULL, /* set_long */
1657 		avro_generic_null_set,
1658 		NULL, /* set_string */
1659 		NULL, /* set_string_length */
1660 		NULL, /* give_string_length */
1661 		NULL, /* set_enum */
1662 		NULL, /* set_fixed */
1663 		NULL, /* give_fixed */
1664 		/* compound getters */
1665 		NULL, /* get_size */
1666 		NULL, /* get_by_index */
1667 		NULL, /* get_by_name */
1668 		NULL, /* get_discriminant */
1669 		NULL, /* get_current_branch */
1670 		/* compound setters */
1671 		NULL, /* append */
1672 		NULL, /* add */
1673 		NULL  /* set_branch */
1674 	},
1675 	avro_generic_null_instance_size,
1676 	avro_generic_null_init,
1677 	avro_generic_null_done
1678 };
1679 
1680 avro_value_iface_t *
1681 avro_generic_null_class(void)
1682 {
1683 	return &AVRO_GENERIC_NULL_CLASS.parent;
1684 }
1685 
1686 int
1687 avro_generic_null_new(avro_value_t *value)
1688 {
1689 	return avro_generic_value_new(&AVRO_GENERIC_NULL_CLASS.parent, value);
1690 }
1691 
1692 /*-----------------------------------------------------------------------
1693  * string
1694  */
1695 
1696 static int
1697 avro_generic_string_reset(const avro_value_iface_t *iface, void *vself)
1698 {
1699 	AVRO_UNUSED(iface);
1700 	avro_raw_string_t  *self = (avro_raw_string_t *) vself;
1701 	avro_raw_string_clear(self);
1702 	return 0;
1703 }
1704 
1705 static avro_type_t
1706 avro_generic_string_get_type(const avro_value_iface_t *iface, const void *vself)
1707 {
1708 	AVRO_UNUSED(iface);
1709 	AVRO_UNUSED(vself);
1710 	return AVRO_STRING;
1711 }
1712 
1713 static avro_schema_t
1714 avro_generic_string_get_schema(const avro_value_iface_t *iface, const void *vself)
1715 {
1716 	AVRO_UNUSED(iface);
1717 	AVRO_UNUSED(vself);
1718 	return avro_schema_string();
1719 }
1720 
1721 static int
1722 avro_generic_string_get(const avro_value_iface_t *iface,
1723 			const void *vself, const char **str, size_t *size)
1724 {
1725 	AVRO_UNUSED(iface);
1726 	const avro_raw_string_t  *self = (const avro_raw_string_t *) vself;
1727 	const char  *contents = (const char *) avro_raw_string_get(self);
1728 
1729 	if (str != NULL) {
1730 		/*
1731 		 * We can't return a NULL string, we have to return an
1732 		 * *empty* string
1733 		 */
1734 
1735 		*str = (contents == NULL)? "": contents;
1736 	}
1737 	if (size != NULL) {
1738 		/* raw_string's length includes the NUL terminator,
1739 		 * unless it's empty */
1740 		*size = (contents == NULL)? 1: avro_raw_string_length(self);
1741 	}
1742 	return 0;
1743 }
1744 
1745 static int
1746 avro_generic_string_grab(const avro_value_iface_t *iface,
1747 			 const void *vself, avro_wrapped_buffer_t *dest)
1748 {
1749 	AVRO_UNUSED(iface);
1750 	const avro_raw_string_t  *self = (const avro_raw_string_t *) vself;
1751 	const char  *contents = (const char *) avro_raw_string_get(self);
1752 
1753 	if (contents == NULL) {
1754 		return avro_wrapped_buffer_new(dest, "", 1);
1755 	} else {
1756 		return avro_raw_string_grab(self, dest);
1757 	}
1758 }
1759 
1760 static int
1761 avro_generic_string_set(const avro_value_iface_t *iface,
1762 			void *vself, const char *val)
1763 {
1764 	AVRO_UNUSED(iface);
1765 	check_param(EINVAL, val != NULL, "string contents");
1766 
1767 	/*
1768 	 * This raw_string method ensures that we copy the NUL
1769 	 * terminator from val, and will include the NUL terminator in
1770 	 * the raw_string's length, which is what we want.
1771 	 */
1772 	avro_raw_string_t  *self = (avro_raw_string_t *) vself;
1773 	avro_raw_string_set(self, val);
1774 	return 0;
1775 }
1776 
1777 static int
1778 avro_generic_string_set_length(const avro_value_iface_t *iface,
1779 			       void *vself, const char *val, size_t size)
1780 {
1781 	AVRO_UNUSED(iface);
1782 	check_param(EINVAL, val != NULL, "string contents");
1783 	avro_raw_string_t  *self = (avro_raw_string_t *) vself;
1784 	avro_raw_string_set_length(self, val, size);
1785 	return 0;
1786 }
1787 
1788 static int
1789 avro_generic_string_give_length(const avro_value_iface_t *iface,
1790 				void *vself, avro_wrapped_buffer_t *buf)
1791 {
1792 	AVRO_UNUSED(iface);
1793 	avro_raw_string_t  *self = (avro_raw_string_t *) vself;
1794 	avro_raw_string_give(self, buf);
1795 	return 0;
1796 }
1797 
1798 static size_t
1799 avro_generic_string_instance_size(const avro_value_iface_t *iface)
1800 {
1801 	AVRO_UNUSED(iface);
1802 	return sizeof(avro_raw_string_t);
1803 }
1804 
1805 static int
1806 avro_generic_string_init(const avro_value_iface_t *iface, void *vself)
1807 {
1808 	AVRO_UNUSED(iface);
1809 	avro_raw_string_t  *self = (avro_raw_string_t *) vself;
1810 	avro_raw_string_init(self);
1811 	return 0;
1812 }
1813 
1814 static void
1815 avro_generic_string_done(const avro_value_iface_t *iface, void *vself)
1816 {
1817 	AVRO_UNUSED(iface);
1818 	avro_raw_string_t  *self = (avro_raw_string_t *) vself;
1819 	avro_raw_string_done(self);
1820 }
1821 
1822 static avro_generic_value_iface_t  AVRO_GENERIC_STRING_CLASS =
1823 {
1824 	{
1825 		/* "class" methods */
1826 		NULL, /* incref_iface */
1827 		NULL, /* decref_iface */
1828 		/* general "instance" methods */
1829 		avro_generic_value_incref,
1830 		avro_generic_value_decref,
1831 		avro_generic_string_reset,
1832 		avro_generic_string_get_type,
1833 		avro_generic_string_get_schema,
1834 		/* primitive getters */
1835 		NULL, /* get_boolean */
1836 		NULL, /* get_bytes */
1837 		NULL, /* grab_bytes */
1838 		NULL, /* get_double */
1839 		NULL, /* get_float */
1840 		NULL, /* get_int */
1841 		NULL, /* get_long */
1842 		NULL, /* get_null */
1843 		avro_generic_string_get,
1844 		avro_generic_string_grab,
1845 		NULL, /* get_enum */
1846 		NULL, /* get_fixed */
1847 		NULL, /* grab_fixed */
1848 		/* primitive setters */
1849 		NULL, /* set_boolean */
1850 		NULL, /* set_bytes */
1851 		NULL, /* give_bytes */
1852 		NULL, /* set_double */
1853 		NULL, /* set_float */
1854 		NULL, /* set_int */
1855 		NULL, /* set_long */
1856 		NULL, /* set_null */
1857 		avro_generic_string_set,
1858 		avro_generic_string_set_length,
1859 		avro_generic_string_give_length,
1860 		NULL, /* set_enum */
1861 		NULL, /* set_fixed */
1862 		NULL, /* give_fixed */
1863 		/* compound getters */
1864 		NULL, /* get_size */
1865 		NULL, /* get_by_index */
1866 		NULL, /* get_by_name */
1867 		NULL, /* get_discriminant */
1868 		NULL, /* get_current_branch */
1869 		/* compound setters */
1870 		NULL, /* append */
1871 		NULL, /* add */
1872 		NULL  /* set_branch */
1873 	},
1874 	avro_generic_string_instance_size,
1875 	avro_generic_string_init,
1876 	avro_generic_string_done
1877 };
1878 
1879 avro_value_iface_t *
1880 avro_generic_string_class(void)
1881 {
1882 	return &AVRO_GENERIC_STRING_CLASS.parent;
1883 }
1884 
1885 int
1886 avro_generic_string_new(avro_value_t *value, const char *str)
1887 {
1888 	int  rval;
1889 	check(rval, avro_generic_value_new(&AVRO_GENERIC_STRING_CLASS.parent, value));
1890 	return avro_generic_string_set(value->iface, value->self, str);
1891 }
1892 
1893 int
1894 avro_generic_string_new_length(avro_value_t *value, const char *str, size_t size)
1895 {
1896 	int  rval;
1897 	check(rval, avro_generic_value_new(&AVRO_GENERIC_STRING_CLASS.parent, value));
1898 	return avro_generic_string_set_length(value->iface, value->self, str, size);
1899 }
1900 
1901 
1902 /*-----------------------------------------------------------------------
1903  * array
1904  */
1905 
1906 /*
1907  * For generic arrays, we need to store the value implementation for the
1908  * array's elements.
1909  */
1910 
1911 typedef struct avro_generic_array_value_iface {
1912 	avro_generic_value_iface_t  parent;
1913 	volatile int  refcount;
1914 	avro_schema_t  schema;
1915 	avro_generic_value_iface_t  *child_giface;
1916 } avro_generic_array_value_iface_t;
1917 
1918 typedef struct avro_generic_array {
1919 	avro_raw_array_t  array;
1920 } avro_generic_array_t;
1921 
1922 
1923 static avro_value_iface_t *
1924 avro_generic_array_incref_iface(avro_value_iface_t *viface)
1925 {
1926 	avro_generic_array_value_iface_t  *iface =
1927 	    container_of(viface, avro_generic_array_value_iface_t, parent);
1928 	avro_refcount_inc(&iface->refcount);
1929 	return viface;
1930 }
1931 
1932 static void
1933 avro_generic_array_decref_iface(avro_value_iface_t *viface)
1934 {
1935 	avro_generic_array_value_iface_t  *iface =
1936 	    container_of(viface, avro_generic_array_value_iface_t, parent);
1937 	if (avro_refcount_dec(&iface->refcount)) {
1938 		avro_schema_decref(iface->schema);
1939 		avro_value_iface_decref(&iface->child_giface->parent);
1940 		avro_freet(avro_generic_array_value_iface_t, iface);
1941 	}
1942 }
1943 
1944 
1945 static void
1946 avro_generic_array_free_elements(const avro_generic_value_iface_t *child_giface,
1947 				 avro_generic_array_t *self)
1948 {
1949 	size_t  i;
1950 	for (i = 0; i < avro_raw_array_size(&self->array); i++) {
1951 		void  *child_self = avro_raw_array_get_raw(&self->array, i);
1952 		avro_value_done(child_giface, child_self);
1953 	}
1954 }
1955 
1956 static int
1957 avro_generic_array_reset(const avro_value_iface_t *viface, void *vself)
1958 {
1959 	const avro_generic_array_value_iface_t  *iface =
1960 	    container_of(viface, avro_generic_array_value_iface_t, parent);
1961 	avro_generic_array_t  *self = (avro_generic_array_t *) vself;
1962 	avro_generic_array_free_elements(iface->child_giface, self);
1963 	avro_raw_array_clear(&self->array);
1964 	return 0;
1965 }
1966 
1967 static avro_type_t
1968 avro_generic_array_get_type(const avro_value_iface_t *viface, const void *vself)
1969 {
1970 	AVRO_UNUSED(viface);
1971 	AVRO_UNUSED(vself);
1972 	return AVRO_ARRAY;
1973 }
1974 
1975 static avro_schema_t
1976 avro_generic_array_get_schema(const avro_value_iface_t *viface, const void *vself)
1977 {
1978 	const avro_generic_array_value_iface_t  *iface =
1979 	    container_of(viface, avro_generic_array_value_iface_t, parent);
1980 	AVRO_UNUSED(vself);
1981 	return iface->schema;
1982 }
1983 
1984 static int
1985 avro_generic_array_get_size(const avro_value_iface_t *viface,
1986 			    const void *vself, size_t *size)
1987 {
1988 	AVRO_UNUSED(viface);
1989 	const avro_generic_array_t  *self = (const avro_generic_array_t *) vself;
1990 	if (size != NULL) {
1991 		*size = avro_raw_array_size(&self->array);
1992 	}
1993 	return 0;
1994 }
1995 
1996 static int
1997 avro_generic_array_get_by_index(const avro_value_iface_t *viface,
1998 				const void *vself, size_t index,
1999 				avro_value_t *child, const char **name)
2000 {
2001 	const avro_generic_array_value_iface_t  *iface =
2002 	    container_of(viface, avro_generic_array_value_iface_t, parent);
2003 	AVRO_UNUSED(name);
2004 	const avro_generic_array_t  *self = (avro_generic_array_t *) vself;
2005 	if (index >= avro_raw_array_size(&self->array)) {
2006 		avro_set_error("Array index %" PRIsz " out of range", index);
2007 		return EINVAL;
2008 	}
2009 	child->iface = &iface->child_giface->parent;
2010 	child->self = avro_raw_array_get_raw(&self->array, index);
2011 	return 0;
2012 }
2013 
2014 static int
2015 avro_generic_array_append(const avro_value_iface_t *viface,
2016 			  void *vself, avro_value_t *child,
2017 			  size_t *new_index)
2018 {
2019 	int  rval;
2020 	const avro_generic_array_value_iface_t  *iface =
2021 	    container_of(viface, avro_generic_array_value_iface_t, parent);
2022 	avro_generic_array_t  *self = (avro_generic_array_t *) vself;
2023 	child->iface = &iface->child_giface->parent;
2024 	child->self = avro_raw_array_append(&self->array);
2025 	if (child->self == NULL) {
2026 		avro_set_error("Couldn't expand array");
2027 		return ENOMEM;
2028 	}
2029 	check(rval, avro_value_init(iface->child_giface, child->self));
2030 	if (new_index != NULL) {
2031 		*new_index = avro_raw_array_size(&self->array) - 1;
2032 	}
2033 	return 0;
2034 }
2035 
2036 static size_t
2037 avro_generic_array_instance_size(const avro_value_iface_t *viface)
2038 {
2039 	AVRO_UNUSED(viface);
2040 	return sizeof(avro_generic_array_t);
2041 }
2042 
2043 static int
2044 avro_generic_array_init(const avro_value_iface_t *viface, void *vself)
2045 {
2046 	const avro_generic_array_value_iface_t  *iface =
2047 	    container_of(viface, avro_generic_array_value_iface_t, parent);
2048 	avro_generic_array_t  *self = (avro_generic_array_t *) vself;
2049 
2050 	size_t  child_size = avro_value_instance_size(iface->child_giface);
2051 	avro_raw_array_init(&self->array, child_size);
2052 	return 0;
2053 }
2054 
2055 static void
2056 avro_generic_array_done(const avro_value_iface_t *viface, void *vself)
2057 {
2058 	const avro_generic_array_value_iface_t  *iface =
2059 	    container_of(viface, avro_generic_array_value_iface_t, parent);
2060 	avro_generic_array_t  *self = (avro_generic_array_t *) vself;
2061 	avro_generic_array_free_elements(iface->child_giface, self);
2062 	avro_raw_array_done(&self->array);
2063 }
2064 
2065 static avro_generic_value_iface_t  AVRO_GENERIC_ARRAY_CLASS =
2066 {
2067 {
2068 	/* "class" methods */
2069 	avro_generic_array_incref_iface,
2070 	avro_generic_array_decref_iface,
2071 	/* general "instance" methods */
2072 	avro_generic_value_incref,
2073 	avro_generic_value_decref,
2074 	avro_generic_array_reset,
2075 	avro_generic_array_get_type,
2076 	avro_generic_array_get_schema,
2077 	/* primitive getters */
2078 	NULL, /* get_boolean */
2079 	NULL, /* get_bytes */
2080 	NULL, /* grab_bytes */
2081 	NULL, /* get_double */
2082 	NULL, /* get_float */
2083 	NULL, /* get_int */
2084 	NULL, /* get_long */
2085 	NULL, /* get_null */
2086 	NULL, /* get_string */
2087 	NULL, /* grab_string */
2088 	NULL, /* get_enum */
2089 	NULL, /* get_fixed */
2090 	NULL, /* grab_fixed */
2091 	/* primitive setters */
2092 	NULL, /* set_boolean */
2093 	NULL, /* set_bytes */
2094 	NULL, /* give_bytes */
2095 	NULL, /* set_double */
2096 	NULL, /* set_float */
2097 	NULL, /* set_int */
2098 	NULL, /* set_long */
2099 	NULL, /* set_null */
2100 	NULL, /* set_string */
2101 	NULL, /* set_string_length */
2102 	NULL, /* give_string_length */
2103 	NULL, /* set_enum */
2104 	NULL, /* set_fixed */
2105 	NULL, /* give_fixed */
2106 	/* compound getters */
2107 	avro_generic_array_get_size,
2108 	avro_generic_array_get_by_index,
2109 	NULL, /* get_by_name */
2110 	NULL, /* get_discriminant */
2111 	NULL, /* get_current_branch */
2112 	/* compound setters */
2113 	avro_generic_array_append,
2114 	NULL, /* add */
2115 	NULL  /* set_branch */
2116 },
2117 	avro_generic_array_instance_size,
2118 	avro_generic_array_init,
2119 	avro_generic_array_done
2120 };
2121 
2122 static avro_generic_value_iface_t *
2123 avro_generic_array_class(avro_schema_t schema, memoize_state_t *state)
2124 {
2125 	avro_schema_t  child_schema = avro_schema_array_items(schema);
2126 	avro_generic_value_iface_t  *child_giface =
2127 	    avro_generic_class_from_schema_memoized(child_schema, state);
2128 	if (child_giface == NULL) {
2129 		return NULL;
2130 	}
2131 
2132 	ssize_t  child_size = avro_value_instance_size(child_giface);
2133 	if (child_size < 0) {
2134 		avro_set_error("Array item class must provide instance_size");
2135 		avro_value_iface_decref(&child_giface->parent);
2136 		return NULL;
2137 	}
2138 
2139 	avro_generic_array_value_iface_t  *iface =
2140 		(avro_generic_array_value_iface_t *) avro_new(avro_generic_array_value_iface_t);
2141 	if (iface == NULL) {
2142 		avro_value_iface_decref(&child_giface->parent);
2143 		return NULL;
2144 	}
2145 
2146 	/*
2147 	 * TODO: Maybe check that schema.items matches
2148 	 * child_iface.get_schema?
2149 	 */
2150 
2151 	iface->parent = AVRO_GENERIC_ARRAY_CLASS;
2152 	iface->refcount = 1;
2153 	iface->schema = avro_schema_incref(schema);
2154 	iface->child_giface = child_giface;
2155 	return &iface->parent;
2156 }
2157 
2158 
2159 /*-----------------------------------------------------------------------
2160  * enum
2161  */
2162 
2163 typedef struct avro_generic_enum_value_iface {
2164 	avro_generic_value_iface_t  parent;
2165 	volatile int  refcount;
2166 	avro_schema_t  schema;
2167 } avro_generic_enum_value_iface_t;
2168 
2169 
2170 static avro_value_iface_t *
2171 avro_generic_enum_incref_iface(avro_value_iface_t *viface)
2172 {
2173 	avro_generic_enum_value_iface_t  *iface =
2174 	    (avro_generic_enum_value_iface_t *) viface;
2175 	avro_refcount_inc(&iface->refcount);
2176 	return viface;
2177 }
2178 
2179 static void
2180 avro_generic_enum_decref_iface(avro_value_iface_t *viface)
2181 {
2182 	avro_generic_enum_value_iface_t  *iface =
2183 	    (avro_generic_enum_value_iface_t *) viface;
2184 	if (avro_refcount_dec(&iface->refcount)) {
2185 		avro_schema_decref(iface->schema);
2186 		avro_freet(avro_generic_enum_value_iface_t, iface);
2187 	}
2188 }
2189 
2190 static int
2191 avro_generic_enum_reset(const avro_value_iface_t *viface, void *vself)
2192 {
2193 	AVRO_UNUSED(viface);
2194 	int  *self = (int *) vself;
2195 	*self = 0;
2196 	return 0;
2197 }
2198 
2199 static avro_type_t
2200 avro_generic_enum_get_type(const avro_value_iface_t *iface, const void *vself)
2201 {
2202 	AVRO_UNUSED(iface);
2203 	AVRO_UNUSED(vself);
2204 	return AVRO_ENUM;
2205 }
2206 
2207 static avro_schema_t
2208 avro_generic_enum_get_schema(const avro_value_iface_t *viface, const void *vself)
2209 {
2210 	const avro_generic_enum_value_iface_t  *iface =
2211 	    container_of(viface, avro_generic_enum_value_iface_t, parent);
2212 	AVRO_UNUSED(vself);
2213 	return iface->schema;
2214 }
2215 
2216 static int
2217 avro_generic_enum_get(const avro_value_iface_t *viface,
2218 		      const void *vself, int *out)
2219 {
2220 	AVRO_UNUSED(viface);
2221 	const int  *self = (const int *) vself;
2222 	*out = *self;
2223 	return 0;
2224 }
2225 
2226 static int
2227 avro_generic_enum_set(const avro_value_iface_t *viface,
2228 		      void *vself, int val)
2229 {
2230 	AVRO_UNUSED(viface);
2231 	int  *self = (int *) vself;
2232 	*self = val;
2233 	return 0;
2234 }
2235 
2236 static size_t
2237 avro_generic_enum_instance_size(const avro_value_iface_t *viface)
2238 {
2239 	AVRO_UNUSED(viface);
2240 	return sizeof(int);
2241 }
2242 
2243 static int
2244 avro_generic_enum_init(const avro_value_iface_t *viface, void *vself)
2245 {
2246 	AVRO_UNUSED(viface);
2247 	int  *self = (int *) vself;
2248 	*self = 0;
2249 	return 0;
2250 }
2251 
2252 static void
2253 avro_generic_enum_done(const avro_value_iface_t *viface, void *vself)
2254 {
2255 	AVRO_UNUSED(viface);
2256 	AVRO_UNUSED(vself);
2257 }
2258 
2259 static avro_generic_value_iface_t  AVRO_GENERIC_ENUM_CLASS =
2260 {
2261 	{
2262 		/* "class" methods */
2263 		avro_generic_enum_incref_iface,
2264 		avro_generic_enum_decref_iface,
2265 		/* general "instance" methods */
2266 		avro_generic_value_incref,
2267 		avro_generic_value_decref,
2268 		avro_generic_enum_reset,
2269 		avro_generic_enum_get_type,
2270 		avro_generic_enum_get_schema,
2271 		/* primitive getters */
2272 		NULL, /* get_boolean */
2273 		NULL, /* get_bytes */
2274 		NULL, /* grab_bytes */
2275 		NULL, /* get_double */
2276 		NULL, /* get_float */
2277 		NULL, /* get_int */
2278 		NULL, /* get_long */
2279 		NULL, /* get_null */
2280 		NULL, /* get_string */
2281 		NULL, /* grab_string */
2282 		avro_generic_enum_get,
2283 		NULL, /* get_fixed */
2284 		NULL, /* grab_fixed */
2285 		/* primitive setters */
2286 		NULL, /* set_boolean */
2287 		NULL, /* set_bytes */
2288 		NULL, /* give_bytes */
2289 		NULL, /* set_double */
2290 		NULL, /* set_float */
2291 		NULL, /* set_int */
2292 		NULL, /* set_long */
2293 		NULL, /* set_null */
2294 		NULL, /* set_string */
2295 		NULL, /* set_string_length */
2296 		NULL, /* give_string_length */
2297 		avro_generic_enum_set,
2298 		NULL, /* set_fixed */
2299 		NULL, /* give_fixed */
2300 		/* compound getters */
2301 		NULL, /* get_size */
2302 		NULL, /* get_by_index */
2303 		NULL, /* get_by_name */
2304 		NULL, /* get_discriminant */
2305 		NULL, /* get_current_branch */
2306 		/* compound setters */
2307 		NULL, /* append */
2308 		NULL, /* add */
2309 		NULL  /* set_branch */
2310 	},
2311 	avro_generic_enum_instance_size,
2312 	avro_generic_enum_init,
2313 	avro_generic_enum_done
2314 };
2315 
2316 static avro_generic_value_iface_t *
2317 avro_generic_enum_class(avro_schema_t schema)
2318 {
2319 	avro_generic_enum_value_iface_t  *iface =
2320 		(avro_generic_enum_value_iface_t *) avro_new(avro_generic_enum_value_iface_t);
2321 	if (iface == NULL) {
2322 		return NULL;
2323 	}
2324 
2325 	iface->parent = AVRO_GENERIC_ENUM_CLASS;
2326 	iface->refcount = 1;
2327 	iface->schema = avro_schema_incref(schema);
2328 	return &iface->parent;
2329 }
2330 
2331 
2332 /*-----------------------------------------------------------------------
2333  * fixed
2334  */
2335 
2336 typedef struct avro_generic_fixed_value_iface {
2337 	avro_generic_value_iface_t  parent;
2338 	volatile int  refcount;
2339 	avro_schema_t  schema;
2340 	size_t  data_size;
2341 } avro_generic_fixed_value_iface_t;
2342 
2343 
2344 static avro_value_iface_t *
2345 avro_generic_fixed_incref_iface(avro_value_iface_t *viface)
2346 {
2347 	avro_generic_fixed_value_iface_t  *iface =
2348 	    container_of(viface, avro_generic_fixed_value_iface_t, parent);
2349 	avro_refcount_inc(&iface->refcount);
2350 	return viface;
2351 }
2352 
2353 static void
2354 avro_generic_fixed_decref_iface(avro_value_iface_t *viface)
2355 {
2356 	avro_generic_fixed_value_iface_t  *iface =
2357 	    container_of(viface, avro_generic_fixed_value_iface_t, parent);
2358 	if (avro_refcount_dec(&iface->refcount)) {
2359 		avro_schema_decref(iface->schema);
2360 		avro_freet(avro_generic_fixed_value_iface_t, iface);
2361 	}
2362 }
2363 
2364 static int
2365 avro_generic_fixed_reset(const avro_value_iface_t *viface, void *vself)
2366 {
2367 	const avro_generic_fixed_value_iface_t  *iface =
2368 	    container_of(viface, avro_generic_fixed_value_iface_t, parent);
2369 	memset(vself, 0, iface->data_size);
2370 	return 0;
2371 }
2372 
2373 static avro_type_t
2374 avro_generic_fixed_get_type(const avro_value_iface_t *iface, const void *vself)
2375 {
2376 	AVRO_UNUSED(iface);
2377 	AVRO_UNUSED(vself);
2378 	return AVRO_FIXED;
2379 }
2380 
2381 static avro_schema_t
2382 avro_generic_fixed_get_schema(const avro_value_iface_t *viface, const void *vself)
2383 {
2384 	const avro_generic_fixed_value_iface_t  *iface =
2385 	    container_of(viface, avro_generic_fixed_value_iface_t, parent);
2386 	AVRO_UNUSED(vself);
2387 	return iface->schema;
2388 }
2389 
2390 static int
2391 avro_generic_fixed_get(const avro_value_iface_t *viface,
2392 		       const void *vself, const void **buf, size_t *size)
2393 {
2394 	const avro_generic_fixed_value_iface_t  *iface =
2395 	    container_of(viface, avro_generic_fixed_value_iface_t, parent);
2396 	if (buf != NULL) {
2397 		*buf = vself;
2398 	}
2399 	if (size != NULL) {
2400 		*size = iface->data_size;
2401 	}
2402 	return 0;
2403 }
2404 
2405 static int
2406 avro_generic_fixed_grab(const avro_value_iface_t *viface,
2407 			const void *vself, avro_wrapped_buffer_t *dest)
2408 {
2409 	const avro_generic_fixed_value_iface_t  *iface =
2410 	    container_of(viface, avro_generic_fixed_value_iface_t, parent);
2411 	return avro_wrapped_buffer_new(dest, vself, iface->data_size);
2412 }
2413 
2414 static int
2415 avro_generic_fixed_set(const avro_value_iface_t *viface,
2416 		       void *vself, void *buf, size_t size)
2417 {
2418 	check_param(EINVAL, buf != NULL, "fixed contents");
2419 	const avro_generic_fixed_value_iface_t  *iface =
2420 	    container_of(viface, avro_generic_fixed_value_iface_t, parent);
2421 	if (size != iface->data_size) {
2422 		avro_set_error("Invalid data size in set_fixed");
2423 		return EINVAL;
2424 	}
2425 	memcpy(vself, buf, size);
2426 	return 0;
2427 }
2428 
2429 static int
2430 avro_generic_fixed_give(const avro_value_iface_t *viface,
2431 			void *vself, avro_wrapped_buffer_t *buf)
2432 {
2433 	int  rval = avro_generic_fixed_set
2434 	    (viface, vself, (void *) buf->buf, buf->size);
2435 	avro_wrapped_buffer_free(buf);
2436 	return rval;
2437 }
2438 
2439 static size_t
2440 avro_generic_fixed_instance_size(const avro_value_iface_t *viface)
2441 {
2442 	const avro_generic_fixed_value_iface_t  *iface =
2443 	    container_of(viface, avro_generic_fixed_value_iface_t, parent);
2444 	return iface->data_size;
2445 }
2446 
2447 static int
2448 avro_generic_fixed_init(const avro_value_iface_t *viface, void *vself)
2449 {
2450 	const avro_generic_fixed_value_iface_t  *iface =
2451 	    container_of(viface, avro_generic_fixed_value_iface_t, parent);
2452 	memset(vself, 0, iface->data_size);
2453 	return 0;
2454 }
2455 
2456 static void
2457 avro_generic_fixed_done(const avro_value_iface_t *viface, void *vself)
2458 {
2459 	AVRO_UNUSED(viface);
2460 	AVRO_UNUSED(vself);
2461 }
2462 
2463 static avro_generic_value_iface_t  AVRO_GENERIC_FIXED_CLASS =
2464 {
2465 	{
2466 		/* "class" methods */
2467 		avro_generic_fixed_incref_iface,
2468 		avro_generic_fixed_decref_iface,
2469 		/* general "instance" methods */
2470 		avro_generic_value_incref,
2471 		avro_generic_value_decref,
2472 		avro_generic_fixed_reset,
2473 		avro_generic_fixed_get_type,
2474 		avro_generic_fixed_get_schema,
2475 		/* primitive getters */
2476 		NULL, /* get_boolean */
2477 		NULL, /* get_bytes */
2478 		NULL, /* grab_bytes */
2479 		NULL, /* get_double */
2480 		NULL, /* get_float */
2481 		NULL, /* get_int */
2482 		NULL, /* get_long */
2483 		NULL, /* get_null */
2484 		NULL, /* get_string */
2485 		NULL, /* grab_string */
2486 		NULL, /* get_enum */
2487 		avro_generic_fixed_get,
2488 		avro_generic_fixed_grab,
2489 		/* primitive setters */
2490 		NULL, /* set_boolean */
2491 		NULL, /* set_bytes */
2492 		NULL, /* give_bytes */
2493 		NULL, /* set_double */
2494 		NULL, /* set_float */
2495 		NULL, /* set_int */
2496 		NULL, /* set_long */
2497 		NULL, /* set_null */
2498 		NULL, /* set_string */
2499 		NULL, /* set_string_length */
2500 		NULL, /* give_string_length */
2501 		NULL, /* set_enum */
2502 		avro_generic_fixed_set,
2503 		avro_generic_fixed_give,
2504 		/* compound getters */
2505 		NULL, /* get_size */
2506 		NULL, /* get_by_index */
2507 		NULL, /* get_by_name */
2508 		NULL, /* get_discriminant */
2509 		NULL, /* get_current_branch */
2510 		/* compound setters */
2511 		NULL, /* append */
2512 		NULL, /* add */
2513 		NULL  /* set_branch */
2514 	},
2515 	avro_generic_fixed_instance_size,
2516 	avro_generic_fixed_init,
2517 	avro_generic_fixed_done
2518 };
2519 
2520 static avro_generic_value_iface_t *
2521 avro_generic_fixed_class(avro_schema_t schema)
2522 {
2523 	avro_generic_fixed_value_iface_t  *iface =
2524 		(avro_generic_fixed_value_iface_t *) avro_new(avro_generic_fixed_value_iface_t);
2525 	if (iface == NULL) {
2526 		return NULL;
2527 	}
2528 
2529 	iface->parent = AVRO_GENERIC_FIXED_CLASS;
2530 	iface->refcount = 1;
2531 	iface->schema = avro_schema_incref(schema);
2532 	iface->data_size = avro_schema_fixed_size(schema);
2533 	return &iface->parent;
2534 }
2535 
2536 
2537 /*-----------------------------------------------------------------------
2538  * map
2539  */
2540 
2541 /*
2542  * For generic maps, we need to store the value implementation for the
2543  * map's elements.
2544  */
2545 
2546 typedef struct avro_generic_map_value_iface {
2547 	avro_generic_value_iface_t  parent;
2548 	volatile int  refcount;
2549 	avro_schema_t  schema;
2550 	avro_generic_value_iface_t  *child_giface;
2551 } avro_generic_map_value_iface_t;
2552 
2553 typedef struct avro_generic_map {
2554 	avro_raw_map_t  map;
2555 } avro_generic_map_t;
2556 
2557 
2558 static avro_value_iface_t *
2559 avro_generic_map_incref_iface(avro_value_iface_t *viface)
2560 {
2561 	avro_generic_map_value_iface_t  *iface =
2562 	    container_of(viface, avro_generic_map_value_iface_t, parent);
2563 	avro_refcount_inc(&iface->refcount);
2564 	return viface;
2565 }
2566 
2567 static void
2568 avro_generic_map_decref_iface(avro_value_iface_t *viface)
2569 {
2570 	avro_generic_map_value_iface_t  *iface =
2571 	    container_of(viface, avro_generic_map_value_iface_t, parent);
2572 	if (avro_refcount_dec(&iface->refcount)) {
2573 		avro_schema_decref(iface->schema);
2574 		avro_value_iface_decref(&iface->child_giface->parent);
2575 		avro_freet(avro_generic_map_value_iface_t, iface);
2576 	}
2577 }
2578 
2579 
2580 static void
2581 avro_generic_map_free_elements(const avro_generic_value_iface_t *child_giface,
2582 			       avro_generic_map_t *self)
2583 {
2584 	size_t  i;
2585 	for (i = 0; i < avro_raw_map_size(&self->map); i++) {
2586 		void  *child_self = avro_raw_map_get_raw(&self->map, i);
2587 		avro_value_done(child_giface, child_self);
2588 	}
2589 }
2590 
2591 static int
2592 avro_generic_map_reset(const avro_value_iface_t *viface, void *vself)
2593 {
2594 	const avro_generic_map_value_iface_t  *iface =
2595 	    container_of(viface, avro_generic_map_value_iface_t, parent);
2596 	avro_generic_map_t  *self = (avro_generic_map_t *) vself;
2597 	avro_generic_map_free_elements(iface->child_giface, self);
2598 	avro_raw_map_clear(&self->map);
2599 	return 0;
2600 }
2601 
2602 static avro_type_t
2603 avro_generic_map_get_type(const avro_value_iface_t *viface, const void *vself)
2604 {
2605 	AVRO_UNUSED(viface);
2606 	AVRO_UNUSED(vself);
2607 	return AVRO_MAP;
2608 }
2609 
2610 static avro_schema_t
2611 avro_generic_map_get_schema(const avro_value_iface_t *viface, const void *vself)
2612 {
2613 	const avro_generic_map_value_iface_t  *iface =
2614 	    container_of(viface, avro_generic_map_value_iface_t, parent);
2615 	AVRO_UNUSED(vself);
2616 	return iface->schema;
2617 }
2618 
2619 static int
2620 avro_generic_map_get_size(const avro_value_iface_t *viface,
2621 			  const void *vself, size_t *size)
2622 {
2623 	AVRO_UNUSED(viface);
2624 	const avro_generic_map_t  *self = (const avro_generic_map_t *) vself;
2625 	if (size != NULL) {
2626 		*size = avro_raw_map_size(&self->map);
2627 	}
2628 	return 0;
2629 }
2630 
2631 static int
2632 avro_generic_map_get_by_index(const avro_value_iface_t *viface,
2633 			      const void *vself, size_t index,
2634 			      avro_value_t *child, const char **name)
2635 {
2636 	const avro_generic_map_value_iface_t  *iface =
2637 	    container_of(viface, avro_generic_map_value_iface_t, parent);
2638 	const avro_generic_map_t  *self = (const avro_generic_map_t *) vself;
2639 	if (index >= avro_raw_map_size(&self->map)) {
2640 		avro_set_error("Map index %" PRIsz " out of range", index);
2641 		return EINVAL;
2642 	}
2643 	child->iface = &iface->child_giface->parent;
2644 	child->self = avro_raw_map_get_raw(&self->map, index);
2645 	if (name != NULL) {
2646 		*name = avro_raw_map_get_key(&self->map, index);
2647 	}
2648 	return 0;
2649 }
2650 
2651 static int
2652 avro_generic_map_get_by_name(const avro_value_iface_t *viface,
2653 			     const void *vself, const char *name,
2654 			     avro_value_t *child, size_t *index)
2655 {
2656 	const avro_generic_map_value_iface_t  *iface =
2657 	    container_of(viface, avro_generic_map_value_iface_t, parent);
2658 	const avro_generic_map_t  *self = (const avro_generic_map_t *) vself;
2659 	child->iface = &iface->child_giface->parent;
2660 	child->self = avro_raw_map_get(&self->map, name, index);
2661 	if (child->self == NULL) {
2662 		avro_set_error("No map element named %s", name);
2663 		return EINVAL;
2664 	}
2665 	return 0;
2666 }
2667 
2668 static int
2669 avro_generic_map_add(const avro_value_iface_t *viface,
2670 		     void *vself, const char *key,
2671 		     avro_value_t *child, size_t *index, int *is_new)
2672 {
2673 	const avro_generic_map_value_iface_t  *iface =
2674 	    container_of(viface, avro_generic_map_value_iface_t, parent);
2675 	int  rval;
2676 	avro_generic_map_t  *self = (avro_generic_map_t *) vself;
2677 	child->iface = &iface->child_giface->parent;
2678 	rval = avro_raw_map_get_or_create(&self->map, key,
2679 					  &child->self, index);
2680 	if (rval < 0) {
2681 		return -rval;
2682 	}
2683 	if (is_new != NULL) {
2684 		*is_new = rval;
2685 	}
2686 	if (rval) {
2687 		check(rval, avro_value_init(iface->child_giface, child->self));
2688 	}
2689 	return 0;
2690 }
2691 
2692 static size_t
2693 avro_generic_map_instance_size(const avro_value_iface_t *viface)
2694 {
2695 	AVRO_UNUSED(viface);
2696 	return sizeof(avro_generic_map_t);
2697 }
2698 
2699 static int
2700 avro_generic_map_init(const avro_value_iface_t *viface, void *vself)
2701 {
2702 	const avro_generic_map_value_iface_t  *iface =
2703 	    container_of(viface, avro_generic_map_value_iface_t, parent);
2704 	avro_generic_map_t  *self = (avro_generic_map_t *) vself;
2705 
2706 	size_t  child_size = avro_value_instance_size(iface->child_giface);
2707 	avro_raw_map_init(&self->map, child_size);
2708 	return 0;
2709 }
2710 
2711 static void
2712 avro_generic_map_done(const avro_value_iface_t *viface, void *vself)
2713 {
2714 	const avro_generic_map_value_iface_t  *iface =
2715 	    container_of(viface, avro_generic_map_value_iface_t, parent);
2716 	avro_generic_map_t  *self = (avro_generic_map_t *) vself;
2717 	avro_generic_map_free_elements(iface->child_giface, self);
2718 	avro_raw_map_done(&self->map);
2719 }
2720 
2721 static avro_generic_value_iface_t  AVRO_GENERIC_MAP_CLASS =
2722 {
2723 	{
2724 		/* "class" methods */
2725 		avro_generic_map_incref_iface,
2726 		avro_generic_map_decref_iface,
2727 		/* general "instance" methods */
2728 		avro_generic_value_incref,
2729 		avro_generic_value_decref,
2730 		avro_generic_map_reset,
2731 		avro_generic_map_get_type,
2732 		avro_generic_map_get_schema,
2733 		/* primitive getters */
2734 		NULL, /* get_boolean */
2735 		NULL, /* get_bytes */
2736 		NULL, /* grab_bytes */
2737 		NULL, /* get_double */
2738 		NULL, /* get_float */
2739 		NULL, /* get_int */
2740 		NULL, /* get_long */
2741 		NULL, /* get_null */
2742 		NULL, /* get_string */
2743 		NULL, /* grab_string */
2744 		NULL, /* get_enum */
2745 		NULL, /* get_fixed */
2746 		NULL, /* grab_fixed */
2747 		/* primitive setters */
2748 		NULL, /* set_boolean */
2749 		NULL, /* set_bytes */
2750 		NULL, /* give_bytes */
2751 		NULL, /* set_double */
2752 		NULL, /* set_float */
2753 		NULL, /* set_int */
2754 		NULL, /* set_long */
2755 		NULL, /* set_null */
2756 		NULL, /* set_string */
2757 		NULL, /* set_string_length */
2758 		NULL, /* give_string_length */
2759 		NULL, /* set_enum */
2760 		NULL, /* set_fixed */
2761 		NULL, /* give_fixed */
2762 		/* compound getters */
2763 		avro_generic_map_get_size,
2764 		avro_generic_map_get_by_index,
2765 		avro_generic_map_get_by_name,
2766 		NULL, /* get_discriminant */
2767 		NULL, /* get_current_branch */
2768 		/* compound setters */
2769 		NULL, /* append */
2770 		avro_generic_map_add,
2771 		NULL  /* set_branch */
2772 	},
2773 	avro_generic_map_instance_size,
2774 	avro_generic_map_init,
2775 	avro_generic_map_done
2776 };
2777 
2778 static avro_generic_value_iface_t *
2779 avro_generic_map_class(avro_schema_t schema, memoize_state_t *state)
2780 {
2781 	avro_schema_t  child_schema = avro_schema_array_items(schema);
2782 	avro_generic_value_iface_t  *child_giface =
2783 	    avro_generic_class_from_schema_memoized(child_schema, state);
2784 	if (child_giface == NULL) {
2785 		return NULL;
2786 	}
2787 
2788 	ssize_t  child_size = avro_value_instance_size(child_giface);
2789 	if (child_size < 0) {
2790 		avro_set_error("Map value class must provide instance_size");
2791 		avro_value_iface_decref(&child_giface->parent);
2792 		return NULL;
2793 	}
2794 
2795 	avro_generic_map_value_iface_t  *iface =
2796 		(avro_generic_map_value_iface_t *) avro_new(avro_generic_map_value_iface_t);
2797 	if (iface == NULL) {
2798 		avro_value_iface_decref(&child_giface->parent);
2799 		return NULL;
2800 	}
2801 
2802 	/*
2803 	 * TODO: Maybe check that schema.items matches
2804 	 * child_iface.get_schema?
2805 	 */
2806 
2807 	iface->parent = AVRO_GENERIC_MAP_CLASS;
2808 	iface->refcount = 1;
2809 	iface->schema = avro_schema_incref(schema);
2810 	iface->child_giface = child_giface;
2811 	return &iface->parent;
2812 }
2813 
2814 
2815 /*-----------------------------------------------------------------------
2816  * record
2817  */
2818 
2819 #ifndef DEBUG_FIELD_OFFSETS
2820 #define DEBUG_FIELD_OFFSETS 0
2821 #endif
2822 
2823 #if DEBUG_FIELD_OFFSETS
2824 #include <stdio.h>
2825 #endif
2826 
2827 /*
2828  * For generic records, we need to store the value implementation for
2829  * each field.  We also need to store an offset for each field, since
2830  * we're going to store the contents of each field directly in the
2831  * record, rather than via pointers.
2832  */
2833 
2834 typedef struct avro_generic_record_value_iface {
2835 	avro_generic_value_iface_t  parent;
2836 	volatile int  refcount;
2837 	avro_schema_t  schema;
2838 
2839 	/** The total size of each value struct for this record. */
2840 	size_t  instance_size;
2841 
2842 	/** The number of fields in this record.  Yes, we could get this
2843 	 * from schema, but this is easier. */
2844 	size_t  field_count;
2845 
2846 	/** The offset of each field within the record struct. */
2847 	size_t  *field_offsets;
2848 
2849 	/** The value implementation for each field. */
2850 	avro_generic_value_iface_t  **field_ifaces;
2851 } avro_generic_record_value_iface_t;
2852 
2853 typedef struct avro_generic_record {
2854 	/* The rest of the struct is taken up by the inline storage
2855 	 * needed for each field. */
2856 } avro_generic_record_t;
2857 
2858 
2859 /** Return a pointer to the given field within a record struct. */
2860 #define avro_generic_record_field(iface, rec, index) \
2861 	(((char *) (rec)) + (iface)->field_offsets[(index)])
2862 
2863 
2864 static avro_value_iface_t *
2865 avro_generic_record_incref_iface(avro_value_iface_t *viface)
2866 {
2867 	avro_generic_record_value_iface_t  *iface =
2868 	    container_of(viface, avro_generic_record_value_iface_t, parent);
2869 	avro_refcount_inc(&iface->refcount);
2870 	return viface;
2871 }
2872 
2873 static void
2874 avro_generic_record_decref_iface(avro_value_iface_t *viface)
2875 {
2876 	avro_generic_record_value_iface_t  *iface =
2877 	    container_of(viface, avro_generic_record_value_iface_t, parent);
2878 
2879 	if (avro_refcount_dec(&iface->refcount)) {
2880 		size_t  i;
2881 		for (i = 0; i < iface->field_count; i++) {
2882 			avro_value_iface_decref(&iface->field_ifaces[i]->parent);
2883 		}
2884 
2885 		avro_schema_decref(iface->schema);
2886 		avro_free(iface->field_offsets,
2887 			  sizeof(size_t) * iface->field_count);
2888 		avro_free(iface->field_ifaces,
2889 			  sizeof(avro_generic_value_iface_t *) * iface->field_count);
2890 
2891 		avro_freet(avro_generic_record_value_iface_t, iface);
2892 	}
2893 }
2894 
2895 
2896 static int
2897 avro_generic_record_reset(const avro_value_iface_t *viface, void *vself)
2898 {
2899 	const avro_generic_record_value_iface_t  *iface =
2900 	    container_of(viface, avro_generic_record_value_iface_t, parent);
2901 	int  rval;
2902 	avro_generic_record_t  *self = (avro_generic_record_t *) vself;
2903 	size_t  i;
2904 	for (i = 0; i < iface->field_count; i++) {
2905 		avro_value_t  value = {
2906 			&iface->field_ifaces[i]->parent,
2907 			avro_generic_record_field(iface, self, i)
2908 		};
2909 		check(rval, avro_value_reset(&value));
2910 	}
2911 	return 0;
2912 }
2913 
2914 static avro_type_t
2915 avro_generic_record_get_type(const avro_value_iface_t *viface, const void *vself)
2916 {
2917 	AVRO_UNUSED(viface);
2918 	AVRO_UNUSED(vself);
2919 	return AVRO_RECORD;
2920 }
2921 
2922 static avro_schema_t
2923 avro_generic_record_get_schema(const avro_value_iface_t *viface, const void *vself)
2924 {
2925 	const avro_generic_record_value_iface_t  *iface =
2926 	    container_of(viface, avro_generic_record_value_iface_t, parent);
2927 	AVRO_UNUSED(vself);
2928 	return iface->schema;
2929 }
2930 
2931 static int
2932 avro_generic_record_get_size(const avro_value_iface_t *viface,
2933 			     const void *vself, size_t *size)
2934 {
2935 	const avro_generic_record_value_iface_t  *iface =
2936 	    container_of(viface, avro_generic_record_value_iface_t, parent);
2937 	AVRO_UNUSED(vself);
2938 	if (size != NULL) {
2939 		*size = iface->field_count;
2940 	}
2941 	return 0;
2942 }
2943 
2944 static int
2945 avro_generic_record_get_by_index(const avro_value_iface_t *viface,
2946 				 const void *vself, size_t index,
2947 				 avro_value_t *child, const char **name)
2948 {
2949 	const avro_generic_record_value_iface_t  *iface =
2950 	    container_of(viface, avro_generic_record_value_iface_t, parent);
2951 	const avro_generic_record_t  *self = (const avro_generic_record_t *) vself;
2952 	if (index >= iface->field_count) {
2953 		avro_set_error("Field index %" PRIsz " out of range", index);
2954 		return EINVAL;
2955 	}
2956 	child->iface = &iface->field_ifaces[index]->parent;
2957 	child->self = avro_generic_record_field(iface, self, index);
2958 
2959 	/*
2960 	 * Grab the field name from the schema if asked for.
2961 	 */
2962 	if (name != NULL) {
2963 		avro_schema_t  schema = iface->schema;
2964 		*name = avro_schema_record_field_name(schema, index);
2965 	}
2966 
2967 	return 0;
2968 }
2969 
2970 static int
2971 avro_generic_record_get_by_name(const avro_value_iface_t *viface,
2972 				const void *vself, const char *name,
2973 				avro_value_t *child, size_t *index_out)
2974 {
2975 	const avro_generic_record_value_iface_t  *iface =
2976 	    container_of(viface, avro_generic_record_value_iface_t, parent);
2977 	const avro_generic_record_t  *self = (const avro_generic_record_t *) vself;
2978 
2979 	avro_schema_t  schema = iface->schema;
2980 	int  index = avro_schema_record_field_get_index(schema, name);
2981 	if (index < 0) {
2982 		avro_set_error("Unknown record field %s", name);
2983 		return EINVAL;
2984 	}
2985 
2986 	child->iface = &iface->field_ifaces[index]->parent;
2987 	child->self = avro_generic_record_field(iface, self, index);
2988 	if (index_out != NULL) {
2989 		*index_out = index;
2990 	}
2991 	return 0;
2992 }
2993 
2994 static size_t
2995 avro_generic_record_instance_size(const avro_value_iface_t *viface)
2996 {
2997 	const avro_generic_record_value_iface_t  *iface =
2998 	    container_of(viface, avro_generic_record_value_iface_t, parent);
2999 	return iface->instance_size;
3000 }
3001 
3002 static int
3003 avro_generic_record_init(const avro_value_iface_t *viface, void *vself)
3004 {
3005 	int  rval;
3006 	const avro_generic_record_value_iface_t  *iface =
3007 	    container_of(viface, avro_generic_record_value_iface_t, parent);
3008 	avro_generic_record_t  *self = (avro_generic_record_t *) vself;
3009 
3010 	/* Initialize each field */
3011 	size_t  i;
3012 	for (i = 0; i < iface->field_count; i++) {
3013 		check(rval, avro_value_init
3014 		      (iface->field_ifaces[i],
3015 		       avro_generic_record_field(iface, self, i)));
3016 	}
3017 
3018 	return 0;
3019 }
3020 
3021 static void
3022 avro_generic_record_done(const avro_value_iface_t *viface, void *vself)
3023 {
3024 	const avro_generic_record_value_iface_t  *iface =
3025 	    container_of(viface, avro_generic_record_value_iface_t, parent);
3026 	avro_generic_record_t  *self = (avro_generic_record_t *) vself;
3027 	size_t  i;
3028 	for (i = 0; i < iface->field_count; i++) {
3029 		avro_value_done(iface->field_ifaces[i],
3030 				avro_generic_record_field(iface, self, i));
3031 	}
3032 }
3033 
3034 static avro_generic_value_iface_t  AVRO_GENERIC_RECORD_CLASS =
3035 {
3036 	{
3037 		/* "class" methods */
3038 		avro_generic_record_incref_iface,
3039 		avro_generic_record_decref_iface,
3040 		/* general "instance" methods */
3041 		avro_generic_value_incref,
3042 		avro_generic_value_decref,
3043 		avro_generic_record_reset,
3044 		avro_generic_record_get_type,
3045 		avro_generic_record_get_schema,
3046 		/* primitive getters */
3047 		NULL, /* get_boolean */
3048 		NULL, /* get_bytes */
3049 		NULL, /* grab_bytes */
3050 		NULL, /* get_double */
3051 		NULL, /* get_float */
3052 		NULL, /* get_int */
3053 		NULL, /* get_long */
3054 		NULL, /* get_null */
3055 		NULL, /* get_string */
3056 		NULL, /* grab_string */
3057 		NULL, /* get_enum */
3058 		NULL, /* get_fixed */
3059 		NULL, /* grab_fixed */
3060 		/* primitive setters */
3061 		NULL, /* set_boolean */
3062 		NULL, /* set_bytes */
3063 		NULL, /* give_bytes */
3064 		NULL, /* set_double */
3065 		NULL, /* set_float */
3066 		NULL, /* set_int */
3067 		NULL, /* set_long */
3068 		NULL, /* set_null */
3069 		NULL, /* set_string */
3070 		NULL, /* set_string_length */
3071 		NULL, /* give_string_length */
3072 		NULL, /* set_enum */
3073 		NULL, /* set_fixed */
3074 		NULL, /* give_fixed */
3075 		/* compound getters */
3076 		avro_generic_record_get_size,
3077 		avro_generic_record_get_by_index,
3078 		avro_generic_record_get_by_name,
3079 		NULL, /* get_discriminant */
3080 		NULL, /* get_current_branch */
3081 		/* compound setters */
3082 		NULL, /* append */
3083 		NULL, /* add */
3084 		NULL  /* set_branch */
3085 	},
3086 	avro_generic_record_instance_size,
3087 	avro_generic_record_init,
3088 	avro_generic_record_done
3089 };
3090 
3091 static avro_generic_value_iface_t *
3092 avro_generic_record_class(avro_schema_t schema, memoize_state_t *state)
3093 {
3094 	avro_generic_record_value_iface_t  *iface =
3095 		(avro_generic_record_value_iface_t *) avro_new(avro_generic_record_value_iface_t);
3096 	if (iface == NULL) {
3097 		return NULL;
3098 	}
3099 
3100 	memset(iface, 0, sizeof(avro_generic_record_value_iface_t));
3101 	iface->parent = AVRO_GENERIC_RECORD_CLASS;
3102 	iface->refcount = 1;
3103 	iface->schema = avro_schema_incref(schema);
3104 
3105 	iface->field_count = avro_schema_record_size(schema);
3106 	size_t  field_offsets_size =
3107 		sizeof(size_t) * iface->field_count;
3108 	size_t  field_ifaces_size =
3109 		sizeof(avro_generic_value_iface_t *) * iface->field_count;
3110 
3111 	if (iface->field_count == 0) {
3112 		iface->field_offsets = NULL;
3113 		iface->field_ifaces = NULL;
3114 	} else {
3115 		iface->field_offsets = (size_t *) avro_malloc(field_offsets_size);
3116 		if (iface->field_offsets == NULL) {
3117 			goto error;
3118 		}
3119 
3120 		iface->field_ifaces = (avro_generic_value_iface_t **) avro_malloc(field_ifaces_size);
3121 		if (iface->field_ifaces == NULL) {
3122 			goto error;
3123 		}
3124 	}
3125 
3126 	size_t  next_offset = sizeof(avro_generic_record_t);
3127 #if DEBUG_FIELD_OFFSETS
3128 	fprintf(stderr, "  Record %s\n  Header: Offset 0, size %" PRIsz "\n",
3129 		avro_schema_type_name(schema),
3130 		sizeof(avro_generic_record_t));
3131 #endif
3132 	size_t  i;
3133 	for (i = 0; i < iface->field_count; i++) {
3134 #if DEBUG_FIELD_OFFSETS
3135 		fprintf(stderr, "  Field %" PRIsz ":\n", i);
3136 #endif
3137 		avro_schema_t  field_schema =
3138 		    avro_schema_record_field_get_by_index(schema, i);
3139 #if DEBUG_FIELD_OFFSETS
3140 		fprintf(stderr, "    Schema %s\n",
3141 			avro_schema_type_name(field_schema));
3142 #endif
3143 
3144 		iface->field_offsets[i] = next_offset;
3145 
3146 		iface->field_ifaces[i] =
3147 		    avro_generic_class_from_schema_memoized(field_schema, state);
3148 		if (iface->field_ifaces[i] == NULL) {
3149 			goto error;
3150 		}
3151 
3152 		ssize_t  field_size =
3153 		    avro_value_instance_size(iface->field_ifaces[i]);
3154 		if (field_size < 0) {
3155 			avro_set_error("Record field class must provide instance_size");
3156 			goto error;
3157 		}
3158 
3159 #if DEBUG_FIELD_OFFSETS
3160 		fprintf(stderr, "    Offset %" PRIsz ", size %" PRIsz "\n",
3161 			next_offset, field_size);
3162 #endif
3163 		next_offset += field_size;
3164 	}
3165 
3166 	iface->instance_size = next_offset;
3167 #if DEBUG_FIELD_OFFSETS
3168 	fprintf(stderr, "  TOTAL SIZE: %" PRIsz "\n", next_offset);
3169 #endif
3170 
3171 	return &iface->parent;
3172 
3173 error:
3174 	avro_schema_decref(iface->schema);
3175 	if (iface->field_offsets != NULL) {
3176 		avro_free(iface->field_offsets, field_offsets_size);
3177 	}
3178 	if (iface->field_ifaces != NULL) {
3179 		for (i = 0; i < iface->field_count; i++) {
3180 			if (iface->field_ifaces[i] != NULL) {
3181 				avro_value_iface_decref(&iface->field_ifaces[i]->parent);
3182 			}
3183 		}
3184 		avro_free(iface->field_ifaces, field_ifaces_size);
3185 	}
3186 	avro_freet(avro_generic_record_value_iface_t, iface);
3187 	return NULL;
3188 }
3189 
3190 
3191 /*-----------------------------------------------------------------------
3192  * union
3193  */
3194 
3195 #ifndef DEBUG_BRANCHES_OFFSETS
3196 #define DEBUG_BRANCHES_OFFSETS 0
3197 #endif
3198 
3199 #if DEBUG_BRANCHES_OFFSETS
3200 #include <stdio.h>
3201 #endif
3202 
3203 /*
3204  * For generic unions, we need to store the value implementation for
3205  * each branch, just like for generic records.  However, for unions, we
3206  * can only have one branch active at a time, so we can reuse the space
3207  * in the union struct, just like is done with C unions.
3208  */
3209 
3210 typedef struct avro_generic_union_value_iface {
3211 	avro_generic_value_iface_t  parent;
3212 	volatile int  refcount;
3213 	avro_schema_t  schema;
3214 
3215 	/** The total size of each value struct for this union. */
3216 	size_t  instance_size;
3217 
3218 	/** The number of branches in this union.  Yes, we could get
3219 	 * this from schema, but this is easier. */
3220 	size_t  branch_count;
3221 
3222 	/** The value implementation for each branch. */
3223 	avro_generic_value_iface_t  **branch_ifaces;
3224 } avro_generic_union_value_iface_t;
3225 
3226 typedef struct avro_generic_union {
3227 	/** The currently active branch of the union.  -1 if no branch
3228 	 * is selected. */
3229 	int  discriminant;
3230 
3231 	/* The rest of the struct is taken up by the inline storage
3232 	 * needed for the active branch. */
3233 } avro_generic_union_t;
3234 
3235 
3236 /** Return the child interface for the active branch. */
3237 #define avro_generic_union_branch_giface(iface, _union) \
3238 	((iface)->branch_ifaces[(_union)->discriminant])
3239 #define avro_generic_union_branch_iface(iface, _union) \
3240 	(&(avro_generic_union_branch_giface((iface), (_union)))->parent)
3241 
3242 /** Return a pointer to the active branch within a union struct. */
3243 #define avro_generic_union_branch(_union) \
3244 	(((char *) (_union)) + sizeof(avro_generic_union_t))
3245 
3246 
3247 static avro_value_iface_t *
3248 avro_generic_union_incref_iface(avro_value_iface_t *viface)
3249 {
3250 	avro_generic_union_value_iface_t  *iface =
3251 	    container_of(viface, avro_generic_union_value_iface_t, parent);
3252 	avro_refcount_inc(&iface->refcount);
3253 	return viface;
3254 }
3255 
3256 static void
3257 avro_generic_union_decref_iface(avro_value_iface_t *viface)
3258 {
3259 	avro_generic_union_value_iface_t  *iface =
3260 	    container_of(viface, avro_generic_union_value_iface_t, parent);
3261 
3262 	if (avro_refcount_dec(&iface->refcount)) {
3263 		size_t  i;
3264 		for (i = 0; i < iface->branch_count; i++) {
3265 			avro_value_iface_decref(&iface->branch_ifaces[i]->parent);
3266 		}
3267 
3268 		avro_schema_decref(iface->schema);
3269 		avro_free(iface->branch_ifaces,
3270 			  sizeof(avro_generic_value_iface_t *) * iface->branch_count);
3271 
3272 		avro_freet(avro_generic_union_value_iface_t, iface);
3273 	}
3274 }
3275 
3276 
3277 static int
3278 avro_generic_union_reset(const avro_value_iface_t *viface, void *vself)
3279 {
3280 	const avro_generic_union_value_iface_t  *iface =
3281 	    container_of(viface, avro_generic_union_value_iface_t, parent);
3282 	avro_generic_union_t  *self = (avro_generic_union_t *) vself;
3283 	/* Keep the same branch selected, for the common case that we're
3284 	 * about to reuse it. */
3285 	if (self->discriminant >= 0) {
3286 #if DEBUG_BRANCHES
3287 		fprintf(stderr, "Resetting branch %d\n",
3288 			self->discriminant);
3289 #endif
3290 		avro_value_t  value = {
3291 			avro_generic_union_branch_iface(iface, self),
3292 			avro_generic_union_branch(self)
3293 		};
3294 		return avro_value_reset(&value);
3295 	}
3296 	return 0;
3297 }
3298 
3299 static avro_type_t
3300 avro_generic_union_get_type(const avro_value_iface_t *viface, const void *vself)
3301 {
3302 	AVRO_UNUSED(viface);
3303 	AVRO_UNUSED(vself);
3304 	return AVRO_UNION;
3305 }
3306 
3307 static avro_schema_t
3308 avro_generic_union_get_schema(const avro_value_iface_t *viface, const void *vself)
3309 {
3310 	const avro_generic_union_value_iface_t  *iface =
3311 	    container_of(viface, avro_generic_union_value_iface_t, parent);
3312 	AVRO_UNUSED(vself);
3313 	return iface->schema;
3314 }
3315 
3316 static int
3317 avro_generic_union_get_discriminant(const avro_value_iface_t *viface,
3318 				    const void *vself, int *out)
3319 {
3320 	AVRO_UNUSED(viface);
3321 	const avro_generic_union_t  *self = (const avro_generic_union_t *) vself;
3322 	*out = self->discriminant;
3323 	return 0;
3324 }
3325 
3326 static int
3327 avro_generic_union_get_current_branch(const avro_value_iface_t *viface,
3328 				      const void *vself, avro_value_t *branch)
3329 {
3330 	const avro_generic_union_value_iface_t  *iface =
3331 	    container_of(viface, avro_generic_union_value_iface_t, parent);
3332 	const avro_generic_union_t  *self = (const avro_generic_union_t *) vself;
3333 	if (self->discriminant < 0) {
3334 		avro_set_error("Union has no selected branch");
3335 		return EINVAL;
3336 	}
3337 	branch->iface = avro_generic_union_branch_iface(iface, self);
3338 	branch->self = avro_generic_union_branch(self);
3339 	return 0;
3340 }
3341 
3342 static int
3343 avro_generic_union_set_branch(const avro_value_iface_t *viface,
3344 			      void *vself, int discriminant,
3345 			      avro_value_t *branch)
3346 {
3347 	const avro_generic_union_value_iface_t  *iface =
3348 	    container_of(viface, avro_generic_union_value_iface_t, parent);
3349 	int  rval;
3350 	avro_generic_union_t  *self = (avro_generic_union_t *) vself;
3351 
3352 #if DEBUG_BRANCHES
3353 	fprintf(stderr, "Selecting branch %d (was %d)\n",
3354 		discriminant, self->discriminant);
3355 #endif
3356 
3357 	/*
3358 	 * If the new desired branch is different than the currently
3359 	 * active one, then finalize the old branch and initialize the
3360 	 * new one.
3361 	 */
3362 	if (self->discriminant != discriminant) {
3363 		if (self->discriminant >= 0) {
3364 #if DEBUG_BRANCHES
3365 			fprintf(stderr, "Finalizing branch %d\n",
3366 				self->discriminant);
3367 #endif
3368 			avro_value_done
3369 			    (avro_generic_union_branch_giface(iface, self),
3370 			     avro_generic_union_branch(self));
3371 		}
3372 		self->discriminant = discriminant;
3373 		if (discriminant >= 0) {
3374 #if DEBUG_BRANCHES
3375 			fprintf(stderr, "Initializing branch %d\n",
3376 				self->discriminant);
3377 #endif
3378 			check(rval, avro_value_init
3379 			      (avro_generic_union_branch_giface(iface, self),
3380 			       avro_generic_union_branch(self)));
3381 		}
3382 	}
3383 
3384 	if (branch != NULL) {
3385 		branch->iface = avro_generic_union_branch_iface(iface, self);
3386 		branch->self = avro_generic_union_branch(self);
3387 	}
3388 
3389 	return 0;
3390 }
3391 
3392 static size_t
3393 avro_generic_union_instance_size(const avro_value_iface_t *viface)
3394 {
3395 	const avro_generic_union_value_iface_t  *iface =
3396 	    container_of(viface, avro_generic_union_value_iface_t, parent);
3397 	return iface->instance_size;
3398 }
3399 
3400 static int
3401 avro_generic_union_init(const avro_value_iface_t *viface, void *vself)
3402 {
3403 	AVRO_UNUSED(viface);
3404 	avro_generic_union_t  *self = (avro_generic_union_t *) vself;
3405 	self->discriminant = -1;
3406 	return 0;
3407 }
3408 
3409 static void
3410 avro_generic_union_done(const avro_value_iface_t *viface, void *vself)
3411 {
3412 	const avro_generic_union_value_iface_t  *iface =
3413 	    container_of(viface, avro_generic_union_value_iface_t, parent);
3414 	avro_generic_union_t  *self = (avro_generic_union_t *) vself;
3415 	if (self->discriminant >= 0) {
3416 #if DEBUG_BRANCHES
3417 		fprintf(stderr, "Finalizing branch %d\n",
3418 			self->discriminant);
3419 #endif
3420 		avro_value_done
3421 		    (avro_generic_union_branch_giface(iface, self),
3422 		     avro_generic_union_branch(self));
3423 		self->discriminant = -1;
3424 	}
3425 }
3426 
3427 static avro_generic_value_iface_t  AVRO_GENERIC_UNION_CLASS =
3428 {
3429 	{
3430 		/* "class" methods */
3431 		avro_generic_union_incref_iface,
3432 		avro_generic_union_decref_iface,
3433 		/* general "instance" methods */
3434 		avro_generic_value_incref,
3435 		avro_generic_value_decref,
3436 		avro_generic_union_reset,
3437 		avro_generic_union_get_type,
3438 		avro_generic_union_get_schema,
3439 		/* primitive getters */
3440 		NULL, /* get_boolean */
3441 		NULL, /* get_bytes */
3442 		NULL, /* grab_bytes */
3443 		NULL, /* get_double */
3444 		NULL, /* get_float */
3445 		NULL, /* get_int */
3446 		NULL, /* get_long */
3447 		NULL, /* get_null */
3448 		NULL, /* get_string */
3449 		NULL, /* grab_string */
3450 		NULL, /* get_enum */
3451 		NULL, /* get_fixed */
3452 		NULL, /* grab_fixed */
3453 		/* primitive setters */
3454 		NULL, /* set_boolean */
3455 		NULL, /* set_bytes */
3456 		NULL, /* give_bytes */
3457 		NULL, /* set_double */
3458 		NULL, /* set_float */
3459 		NULL, /* set_int */
3460 		NULL, /* set_long */
3461 		NULL, /* set_null */
3462 		NULL, /* set_string */
3463 		NULL, /* set_string_length */
3464 		NULL, /* give_string_length */
3465 		NULL, /* set_enum */
3466 		NULL, /* set_fixed */
3467 		NULL, /* give_fixed */
3468 		/* compound getters */
3469 		NULL, /* get_size */
3470 		NULL, /* get_by_index */
3471 		NULL, /* get_by_name */
3472 		avro_generic_union_get_discriminant,
3473 		avro_generic_union_get_current_branch,
3474 		/* compound setters */
3475 		NULL, /* append */
3476 		NULL, /* add */
3477 		avro_generic_union_set_branch
3478 	},
3479 	avro_generic_union_instance_size,
3480 	avro_generic_union_init,
3481 	avro_generic_union_done
3482 };
3483 
3484 static avro_generic_value_iface_t *
3485 avro_generic_union_class(avro_schema_t schema, memoize_state_t *state)
3486 {
3487 	avro_generic_union_value_iface_t  *iface =
3488 		(avro_generic_union_value_iface_t *) avro_new(avro_generic_union_value_iface_t);
3489 	if (iface == NULL) {
3490 		return NULL;
3491 	}
3492 
3493 	memset(iface, 0, sizeof(avro_generic_union_value_iface_t));
3494 	iface->parent = AVRO_GENERIC_UNION_CLASS;
3495 	iface->refcount = 1;
3496 	iface->schema = avro_schema_incref(schema);
3497 
3498 	iface->branch_count = avro_schema_union_size(schema);
3499 	size_t  branch_ifaces_size =
3500 		sizeof(avro_generic_value_iface_t *) * iface->branch_count;
3501 
3502 	iface->branch_ifaces = (avro_generic_value_iface_t **) avro_malloc(branch_ifaces_size);
3503 	if (iface->branch_ifaces == NULL) {
3504 		goto error;
3505 	}
3506 
3507 	size_t  max_branch_size = 0;
3508 	size_t  i;
3509 	for (i = 0; i < iface->branch_count; i++) {
3510 		avro_schema_t  branch_schema =
3511 		    avro_schema_union_branch(schema, i);
3512 
3513 		iface->branch_ifaces[i] =
3514 		    avro_generic_class_from_schema_memoized(branch_schema, state);
3515 		if (iface->branch_ifaces[i] == NULL) {
3516 			goto error;
3517 		}
3518 
3519 		ssize_t  branch_size =
3520 		    avro_value_instance_size(iface->branch_ifaces[i]);
3521 		if (branch_size < 0) {
3522 			avro_set_error("Union branch class must provide instance_size");
3523 			goto error;
3524 		}
3525 
3526 #if DEBUG_BRANCHES
3527 		fprintf(stderr, "Branch %" PRIsz ", size %" PRIsz "\n",
3528 			i, branch_size);
3529 #endif
3530 
3531 		if ((size_t)branch_size > max_branch_size) {
3532 			max_branch_size = (size_t)branch_size;
3533 		}
3534 	}
3535 
3536 	iface->instance_size =
3537 		sizeof(avro_generic_union_t) + max_branch_size;
3538 #if DEBUG_BRANCHES
3539 	fprintf(stderr, "MAX BRANCH SIZE: %" PRIsz "\n", max_branch_size);
3540 #endif
3541 
3542 	return &iface->parent;
3543 
3544 error:
3545 	avro_schema_decref(iface->schema);
3546 	if (iface->branch_ifaces != NULL) {
3547 		for (i = 0; i < iface->branch_count; i++) {
3548 			if (iface->branch_ifaces[i] != NULL) {
3549 				avro_value_iface_decref(&iface->branch_ifaces[i]->parent);
3550 			}
3551 		}
3552 		avro_free(iface->branch_ifaces, branch_ifaces_size);
3553 	}
3554 	avro_freet(avro_generic_union_value_iface_t, iface);
3555 	return NULL;
3556 }
3557 
3558 
3559 /*-----------------------------------------------------------------------
3560  * Schema type dispatcher
3561  */
3562 
3563 static avro_generic_value_iface_t *
3564 avro_generic_class_from_schema_memoized(avro_schema_t schema,
3565 					memoize_state_t *state)
3566 {
3567 	/*
3568 	 * If we've already instantiated a value class for this schema,
3569 	 * just return it.
3570 	 */
3571 
3572 	avro_generic_value_iface_t  *result = NULL;
3573 	if (avro_memoize_get(&state->mem, schema, NULL, (void **) &result)) {
3574 		avro_value_iface_incref(&result->parent);
3575 		return result;
3576 	}
3577 
3578 	/*
3579 	 * Otherwise instantiate the value class based on the schema
3580 	 * type.
3581 	 */
3582 
3583 	switch (schema->type) {
3584 	case AVRO_BOOLEAN:
3585 		result = &AVRO_GENERIC_BOOLEAN_CLASS;
3586 		break;
3587 	case AVRO_BYTES:
3588 		result = &AVRO_GENERIC_BYTES_CLASS;
3589 		break;
3590 	case AVRO_DOUBLE:
3591 		result = &AVRO_GENERIC_DOUBLE_CLASS;
3592 		break;
3593 	case AVRO_FLOAT:
3594 		result = &AVRO_GENERIC_FLOAT_CLASS;
3595 		break;
3596 	case AVRO_INT32:
3597 		result = &AVRO_GENERIC_INT_CLASS;
3598 		break;
3599 	case AVRO_INT64:
3600 		result = &AVRO_GENERIC_LONG_CLASS;
3601 		break;
3602 	case AVRO_NULL:
3603 		result = &AVRO_GENERIC_NULL_CLASS;
3604 		break;
3605 	case AVRO_STRING:
3606 		result = &AVRO_GENERIC_STRING_CLASS;
3607 		break;
3608 
3609 	case AVRO_ARRAY:
3610 		result = avro_generic_array_class(schema, state);
3611 		break;
3612 	case AVRO_ENUM:
3613 		result = avro_generic_enum_class(schema);
3614 		break;
3615 	case AVRO_FIXED:
3616 		result = avro_generic_fixed_class(schema);
3617 		break;
3618 	case AVRO_MAP:
3619 		result = avro_generic_map_class(schema, state);
3620 		break;
3621 	case AVRO_RECORD:
3622 		result = avro_generic_record_class(schema, state);
3623 		break;
3624 	case AVRO_UNION:
3625 		result = avro_generic_union_class(schema, state);
3626 		break;
3627 
3628 	case AVRO_LINK:
3629 		{
3630 			avro_generic_link_value_iface_t  *lresult =
3631 			    avro_generic_link_class(schema);
3632 			lresult->next = state->links;
3633 			state->links = lresult;
3634 			result = &lresult->parent;
3635 			break;
3636 		}
3637 
3638 	default:
3639 		avro_set_error("Unknown schema type");
3640 		return NULL;
3641 	}
3642 
3643 	/*
3644 	 * Add the new value implementation to the memoized state before
3645 	 * we return.
3646 	 */
3647 
3648 	avro_memoize_set(&state->mem, schema, NULL, result);
3649 	return result;
3650 }
3651 
3652 avro_value_iface_t *
3653 avro_generic_class_from_schema(avro_schema_t schema)
3654 {
3655 	/*
3656 	 * Create a state to keep track of the value implementations
3657 	 * that we create for each subschema.
3658 	 */
3659 
3660 	memoize_state_t  state;
3661 	avro_memoize_init(&state.mem);
3662 	state.links = NULL;
3663 
3664 	/*
3665 	 * Create the value implementations.
3666 	 */
3667 
3668 	avro_generic_value_iface_t  *result =
3669 	    avro_generic_class_from_schema_memoized(schema, &state);
3670 	if (result == NULL) {
3671 		avro_memoize_done(&state.mem);
3672 		return NULL;
3673 	}
3674 
3675 	/*
3676 	 * Fix up any link schemas so that their value implementations
3677 	 * point to their target schemas' implementations.
3678 	 */
3679 
3680 	while (state.links != NULL) {
3681 		avro_generic_link_value_iface_t  *link_iface = state.links;
3682 		avro_schema_t  target_schema =
3683 		    avro_schema_link_target(link_iface->schema);
3684 
3685 		avro_generic_value_iface_t  *target_iface = NULL;
3686 		if (!avro_memoize_get(&state.mem, target_schema, NULL,
3687 				      (void **) &target_iface)) {
3688 			avro_set_error("Never created a value implementation for %s",
3689 				       avro_schema_type_name(target_schema));
3690 			return NULL;
3691 		}
3692 
3693 		/* We don't keep a reference to the target
3694 		 * implementation, since that would give us a reference
3695 		 * cycle. */
3696 		link_iface->target_giface = target_iface;
3697 		state.links = link_iface->next;
3698 		link_iface->next = NULL;
3699 	}
3700 
3701 	/*
3702 	 * And now we can return.
3703 	 */
3704 
3705 	avro_memoize_done(&state.mem);
3706 	return &result->parent;
3707 }
3708