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 
21 #include "avro/basics.h"
22 #include "avro/io.h"
23 #include "avro/value.h"
24 #include "avro_private.h"
25 #include "encoding.h"
26 
27 
28 static int
29 write_array_value(avro_writer_t writer, avro_value_t *src)
30 {
31 	int  rval;
32 	size_t  element_count;
33 	check(rval, avro_value_get_size(src, &element_count));
34 
35 	if (element_count > 0) {
36 		check_prefix(rval, avro_binary_encoding.write_long
37 			     (writer, element_count),
38 			     "Cannot write array block count: ");
39 
40 		size_t  i;
41 		for (i = 0; i < element_count; i++) {
42 			avro_value_t  child;
43 			check(rval, avro_value_get_by_index(src, i, &child, NULL));
44 			check(rval, avro_value_write(writer, &child));
45 		}
46 	}
47 
48 	check_prefix(rval, avro_binary_encoding.write_long(writer, 0),
49 		     "Cannot write array block count: ");
50 	return 0;
51 }
52 
53 
54 static int
55 write_map_value(avro_writer_t writer, avro_value_t *src)
56 {
57 	int  rval;
58 	size_t  element_count;
59 	check(rval, avro_value_get_size(src, &element_count));
60 
61 	if (element_count > 0) {
62 		check_prefix(rval, avro_binary_encoding.write_long
63 			     (writer, element_count),
64 			     "Cannot write map block count: ");
65 
66 		size_t  i;
67 		for (i = 0; i < element_count; i++) {
68 			avro_value_t  child;
69 			const char  *key;
70 			check(rval, avro_value_get_by_index(src, i, &child, &key));
71 			check(rval, avro_binary_encoding.write_string(writer, key));
72 			check(rval, avro_value_write(writer, &child));
73 		}
74 	}
75 
76 	check_prefix(rval, avro_binary_encoding.write_long(writer, 0),
77 		     "Cannot write map block count: ");
78 	return 0;
79 }
80 
81 static int
82 write_record_value(avro_writer_t writer, avro_value_t *src)
83 {
84 	int  rval;
85 	size_t  field_count;
86 	check(rval, avro_value_get_size(src, &field_count));
87 
88 	size_t  i;
89 	for (i = 0; i < field_count; i++) {
90 		avro_value_t  field;
91 		check(rval, avro_value_get_by_index(src, i, &field, NULL));
92 		check(rval, avro_value_write(writer, &field));
93 	}
94 
95 	return 0;
96 }
97 
98 static int
99 write_union_value(avro_writer_t writer, avro_value_t *src)
100 {
101 	int  rval;
102 	int  discriminant;
103 	avro_value_t  branch;
104 
105 	check(rval, avro_value_get_discriminant(src, &discriminant));
106 	check(rval, avro_value_get_current_branch(src, &branch));
107 	check(rval, avro_binary_encoding.write_long(writer, discriminant));
108 	return avro_value_write(writer, &branch);
109 }
110 
111 int
112 avro_value_write(avro_writer_t writer, avro_value_t *src)
113 {
114 	int  rval;
115 
116 	switch (avro_value_get_type(src)) {
117 		case AVRO_BOOLEAN:
118 		{
119 			int  val;
120 			check(rval, avro_value_get_boolean(src, &val));
121 			return avro_binary_encoding.write_boolean(writer, val);
122 		}
123 
124 		case AVRO_BYTES:
125 		{
126 			const void  *buf;
127 			size_t  size;
128 			check(rval, avro_value_get_bytes(src, &buf, &size));
129 			return avro_binary_encoding.write_bytes(writer, (const char *) buf, size);
130 		}
131 
132 		case AVRO_DOUBLE:
133 		{
134 			double  val;
135 			check(rval, avro_value_get_double(src, &val));
136 			return avro_binary_encoding.write_double(writer, val);
137 		}
138 
139 		case AVRO_FLOAT:
140 		{
141 			float  val;
142 			check(rval, avro_value_get_float(src, &val));
143 			return avro_binary_encoding.write_float(writer, val);
144 		}
145 
146 		case AVRO_INT32:
147 		{
148 			int32_t  val;
149 			check(rval, avro_value_get_int(src, &val));
150 			return avro_binary_encoding.write_long(writer, val);
151 		}
152 
153 		case AVRO_INT64:
154 		{
155 			int64_t  val;
156 			check(rval, avro_value_get_long(src, &val));
157 			return avro_binary_encoding.write_long(writer, val);
158 		}
159 
160 		case AVRO_NULL:
161 		{
162 			check(rval, avro_value_get_null(src));
163 			return avro_binary_encoding.write_null(writer);
164 		}
165 
166 		case AVRO_STRING:
167 		{
168 			const char  *str;
169 			size_t  size;
170 			check(rval, avro_value_get_string(src, &str, &size));
171 			return avro_binary_encoding.write_bytes(writer, str, size-1);
172 		}
173 
174 		case AVRO_ARRAY:
175 			return write_array_value(writer, src);
176 
177 		case AVRO_ENUM:
178 		{
179 			int  val;
180 			check(rval, avro_value_get_enum(src, &val));
181 			return avro_binary_encoding.write_long(writer, val);
182 		}
183 
184 		case AVRO_FIXED:
185 		{
186 			const void  *buf;
187 			size_t  size;
188 			check(rval, avro_value_get_fixed(src, &buf, &size));
189 			return avro_write(writer, (void *) buf, size);
190 		}
191 
192 		case AVRO_MAP:
193 			return write_map_value(writer, src);
194 
195 		case AVRO_RECORD:
196 			return write_record_value(writer, src);
197 
198 		case AVRO_UNION:
199 			return write_union_value(writer, src);
200 
201 		default:
202 		{
203 			avro_set_error("Unknown schema type");
204 			return EINVAL;
205 		}
206 	}
207 
208 	return 0;
209 }
210