Parse a `serde_json::Value` representing a complex Avro type into a `Schema`. Avro supports "recursive" definition of types. e.g: `{"type": {"type": "string"}}`
(
&mut self,
complex: &Map<String, Value>,
enclosing_namespace: NamespaceRef,
)
| 249 | parser: &mut Parser, |
| 250 | enclosing_namespace: NamespaceRef, |
| 251 | ) -> AvroResult<Schema> { |
| 252 | match complex.remove("type") { |
| 253 | Some(value) => match value { |
| 254 | Value::String(s) if s == "fixed" => { |
| 255 | parser.parse_fixed(complex, enclosing_namespace) |
| 256 | } |
| 257 | _ => parser.parse(value, enclosing_namespace), |
| 258 | }, |
| 259 | None => Err(Details::GetLogicalTypeField.into()), |
| 260 | } |
| 261 | } |
| 262 | |
| 263 | // This crate supports some logical types natively, and this function tries to convert |
| 264 | // a native complex type with a logical type attribute to these logical types. |
| 265 | // This function: |
| 266 | // 1. Checks whether the native complex type is in the supported kinds. |
| 267 | // 2. If it is, using the convert function to convert the native complex type to |
| 268 | // a logical type. |
| 269 | fn try_convert_to_logical_type<F>( |
| 270 | logical_type: &str, |
| 271 | schema: Schema, |
| 272 | supported_schema_kinds: &[SchemaKind], |
| 273 | convert: F, |
| 274 | ) -> AvroResult<Schema> |
| 275 | where |
| 276 | F: Fn(Schema) -> AvroResult<Schema>, |
| 277 | { |
| 278 | let kind = SchemaKind::from(schema.clone()); |
| 279 | if supported_schema_kinds.contains(&kind) { |
| 280 | convert(schema) |
| 281 | } else { |
| 282 | warn!( |
| 283 | "Ignoring unknown logical type '{logical_type}' for schema of type: {schema:?}!" |
| 284 | ); |
| 285 | Ok(schema) |
| 286 | } |
| 287 | } |
| 288 | |
| 289 | match complex.remove_entry("logicalType") { |
| 290 | Some((key, Value::String(t))) => match t.as_str() { |
| 291 | "decimal" => { |
| 292 | return try_convert_to_logical_type( |
| 293 | "decimal", |
| 294 | // TODO: See if we can avoid this clone, although if this really is a decimal |
| 295 | // the clone is cheap enough not to be a problem |
| 296 | parse_as_native_complex(complex.clone(), self, enclosing_namespace)?, |
| 297 | &[SchemaKind::Fixed, SchemaKind::Bytes], |
| 298 | |inner| -> AvroResult<Schema> { |
| 299 | match self.parse_precision_and_scale(&complex) { |
| 300 | Ok((precision, scale)) => Ok(Schema::Decimal(DecimalSchema { |
| 301 | precision, |
| 302 | scale, |
| 303 | inner: inner.try_into()?, |
| 304 | })), |
| 305 | Err(err) => { |
| 306 | warn!("Ignoring invalid decimal logical type: {err}"); |
| 307 | Ok(inner) |
| 308 | } |
no test coverage detected