martin-g commented on code in PR #190: URL: https://github.com/apache/avro-rs/pull/190#discussion_r2064571535
########## avro/src/headers.rs: ########## @@ -0,0 +1,173 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! Handling of Avro magic headers +use uuid::Uuid; + +use crate::{rabin::Rabin, schema::SchemaFingerprint, AvroResult, Schema}; + +/// This trait represents that an object is able to construct an Avro message header. It is +/// implemented for some known header types already. If you need a header type that is not already +/// included here, then you can create your own struct and implement this trait. +pub trait HeaderBuilder { + fn build_header(&self) -> Vec<u8>; +} + +/// HeaderBuilder based on the Rabin schema fingerprint +/// +/// This is the default and will be used automatically by the `new` impls in +/// [crate::reader::GenericSingleObjectReader] and [crate::writer::GenericSingleObjectWriter]. +pub struct RabinFingerprintHeader { + fingerprint: SchemaFingerprint, +} + +impl RabinFingerprintHeader { + /// Use this helper to build an instance from an existing Avro `Schema`. + pub fn from_schema(schema: &Schema) -> Self { + let fingerprint = schema.fingerprint::<Rabin>(); + RabinFingerprintHeader { fingerprint } + } +} + +impl HeaderBuilder for RabinFingerprintHeader { + fn build_header(&self) -> Vec<u8> { + let bytes = &self.fingerprint.bytes; + vec![ + 0xC3, 0x01, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], + bytes[7], + ] + } +} + +/// HeaderBuilder based on +/// [Glue](https://docs.aws.amazon.com/glue/latest/dg/what-is-glue.html) schema UUID +/// +/// See the function docs for usage details +pub struct GlueSchemaUuidHeader { + schema_uuid: Uuid, +} + +impl GlueSchemaUuidHeader { + /// Create an instance of the struct from a Glue Schema UUID + /// + /// Code for writing messages will most likely want to use this. You will need to determine + /// via other means the correct Glue schema UUID and use it with this method to be able to + /// create Avro-encoded messages with the correct headers. + pub fn from_uuid(schema_uuid: Uuid) -> Self { + GlueSchemaUuidHeader { schema_uuid } + } + + /// Create an instance of the struct based on parsing the UUID out of the header of a raw + /// message + /// + /// Code for reading messages will most likely want to use this. Once you receive the raw bytes + /// of a message, use this function to build the struct from it. That struct can then be used + /// with the below `schema_uuid` function to retrieve the UUID in order to retrieve the correct + /// schema for the message. You can then use the raw message, the schema, and the struct + /// instance to read the message. + pub fn parse_from_raw_avro(message_payload: &[u8]) -> AvroResult<Self> { + if message_payload.len() < 19 { + return Err(crate::error::Error::HeaderMagic); + } + let schema_uuid = + Uuid::from_slice(&message_payload[2..18]).map_err(crate::Error::UuidFromSlice)?; Review Comment: I try to minimize the usage of `Result::unwrap()` as much as possible. A library should not panic! The user/caller should be able to react. Without this conversion I was not able to use `?` instead of `.unwrap()`. I will add usage of ``` #![deny( clippy::unwrap_used, clippy::expect_used, clippy::panic )] ``` in another PR! -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
