rocketmq-protocol 1.0.0

Runtime-neutral RocketMQ wire protocol contracts
Documentation
// Copyright 2026 The RocketMQ Rust Authors
//
// Licensed 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.

use super::EncodeSink;
use super::HeaderFieldSource;
use super::HeaderFieldSpec;
use super::HeaderFlattenSpec;
use super::ProtocolContractViolation;
use super::ResolvedHeaderKey;
use crate::HeaderMap;

/// Statically dispatched codec contract for an explicit request-header schema.
///
/// Implementations are generated by `RequestHeaderCodec`. Map and binary
/// destinations share [`Self::encode_into`], so validation, canonical keys,
/// Java ranges, flattening, and value conversion cannot diverge by format.
pub trait HeaderCodec: Sized {
    /// Stable, fully qualified Rust schema identifier.
    const TYPE_ID: &'static str;
    /// Rust header name used in diagnostics.
    const HEADER_NAME: &'static str;
    /// Fully qualified Java peer when one is declared.
    const JAVA_CLASS: Option<&'static str>;
    /// Recursive upper bound used to reserve map entries.
    const FIELD_COUNT_HINT: usize;
    /// Fields declared directly by this header, in stable binary order.
    const LOCAL_FIELD_SPECS: &'static [HeaderFieldSpec];
    /// Flatten groups declared directly by this header, in stable binary order.
    const LOCAL_FLATTEN_SPECS: &'static [HeaderFlattenSpec];
    /// Whether direct binary generation was requested for the schema.
    const FAST_ENABLED: bool;

    /// Validates this header layer before it writes to a wire destination.
    ///
    /// # Errors
    ///
    /// Returns a classified structural or header-specific validation failure.
    fn validate_for_wire(&self) -> Result<(), ProtocolContractViolation>;

    /// Appends canonical fields to a statically dispatched destination.
    ///
    /// # Errors
    ///
    /// Returns a typed validation, range, or destination representation error.
    fn encode_into<S: EncodeSink>(&self, sink: &mut S) -> Result<(), ProtocolContractViolation>;

    /// Decodes this header from borrowed extension fields.
    ///
    /// # Errors
    ///
    /// Returns a typed missing, conflict, conversion, range, or validation error.
    fn decode_from_map(map: &HeaderMap) -> Result<Self, ProtocolContractViolation>;

    /// Decodes this header directly from a borrowed field source.
    ///
    /// Generated request-header codecs override this method with a zero-materialization
    /// scan. The default keeps manually implemented codecs source-compatible.
    ///
    /// # Errors
    ///
    /// Returns the same classified failures as [`Self::decode_from_map`].
    #[inline]
    fn decode_from_source(source: &dyn HeaderFieldSource) -> Result<Self, ProtocolContractViolation> {
        let map = source.to_header_map();
        Self::decode_from_map(&map)
    }

    /// Returns whether this header or any flattened child owns a present key.
    fn contains_any_field(map: &HeaderMap) -> bool;

    /// Returns whether this header or a flattened child owns a source field.
    #[inline]
    fn contains_any_field_source(source: &dyn HeaderFieldSource) -> bool {
        let mut contains = false;
        source.visit_fields_while(&mut |key, _value| {
            if Self::contains_wire_key(key) {
                contains = true;
                false
            } else {
                true
            }
        });
        contains
    }

    /// Estimates the encoded ROCKETMQ extension-field payload length.
    ///
    /// The result saturates at [`usize::MAX`]. It is a capacity hint and does
    /// not validate the header or guarantee that a specific format can encode it.
    fn encoded_len_hint(&self) -> usize;

    /// Visits field schemas declared here and recursively by flattened headers.
    fn visit_field_specs(visitor: &mut dyn FnMut(&HeaderFieldSpec));

    /// Visits flatten schemas declared here and recursively by flattened headers.
    fn visit_flatten_specs(visitor: &mut dyn FnMut(&HeaderFlattenSpec));

    /// Resolves a canonical key or alias to its owning typed field.
    fn resolve_wire_key(key: &str) -> Option<ResolvedHeaderKey>;

    /// Resolves a key and returns its canonical wire key.
    #[inline]
    fn canonical_wire_key(key: &str) -> Option<&'static str> {
        Self::resolve_wire_key(key).map(|resolved| resolved.canonical)
    }

    /// Returns whether a canonical key or alias belongs to this schema.
    #[inline]
    fn contains_wire_key(key: &str) -> bool {
        Self::resolve_wire_key(key).is_some()
    }
}