Skip to main content

base_message/
field_ref.rs

1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4use crate::__private::{IncomingField, IncomingName};
5use std::fmt;
6
7/// One field, borrowed, with its position in the original section.
8///
9/// [`FieldSection::partition`](crate::FieldSection::partition) returns the fields a section does not take as `FieldRef`s, so that the next section reports errors at their original positions.
10#[derive(Clone, Copy, PartialEq, Eq, Hash)]
11pub struct FieldRef<'a> {
12    position: usize,
13    name: &'a str,
14    value: &'a [u8],
15}
16
17impl<'a> FieldRef<'a> {
18    /// A field at a position in the original section.
19    pub const fn new(position: usize, name: &'a str, value: &'a [u8]) -> Self {
20        Self {
21            position,
22            name,
23            value,
24        }
25    }
26
27    /// The field's position in the original section.
28    pub const fn position(&self) -> usize {
29        self.position
30    }
31
32    /// The name as it was written.
33    pub const fn name(&self) -> &'a str {
34        self.name
35    }
36
37    /// The value, as it was passed to the section.
38    pub const fn value(&self) -> &'a [u8] {
39        self.value
40    }
41}
42
43/// Shows the value's length rather than its bytes, since values such as `Authorization` and `Cookie` carry credentials that must not reach logs.
44impl fmt::Debug for FieldRef<'_> {
45    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
46        debug_field(formatter, "FieldRef", self.position, self.name, self.value)
47    }
48}
49
50/// A field's debug representation, with its value redacted to its length.
51pub(crate) fn debug_field(
52    formatter: &mut fmt::Formatter<'_>,
53    type_name: &str,
54    position: usize,
55    name: &str,
56    value: &[u8],
57) -> fmt::Result {
58    formatter
59        .debug_struct(type_name)
60        .field("position", &position)
61        .field("name", &name)
62        .field("value", &format_args!("<{} bytes>", value.len()))
63        .finish()
64}
65
66/// Something section `S` can interpret as one field.
67///
68/// - A `(name, value)` pair, with the value as bytes or text, whose position is its place in the input.
69/// - A [`FieldRef`], which keeps its own position, such as one from a remainder, and an [`OwnedField`](crate::OwnedField) by reference likewise.
70/// - A [`StaticTableEntry`](crate::StaticTableEntry) or [`FieldName`](crate::FieldName) with its value, classified by a static table built for `S`.
71///
72/// It is implemented only by this crate.
73pub trait IntoField<'a, S> {
74    #[doc(hidden)]
75    fn into_field(self, index: usize) -> IncomingField<'a>;
76}
77
78impl<'a, S> IntoField<'a, S> for (&'a str, &'a [u8]) {
79    fn into_field(self, index: usize) -> IncomingField<'a> {
80        IncomingField {
81            position: index,
82            name: IncomingName::Text(self.0),
83            value: self.1,
84        }
85    }
86}
87
88impl<'a, S> IntoField<'a, S> for (&'a str, &'a str) {
89    fn into_field(self, index: usize) -> IncomingField<'a> {
90        IncomingField {
91            position: index,
92            name: IncomingName::Text(self.0),
93            value: self.1.as_bytes(),
94        }
95    }
96}
97
98impl<'a, S> IntoField<'a, S> for &(&'a str, &'a [u8]) {
99    fn into_field(self, index: usize) -> IncomingField<'a> {
100        IncomingField {
101            position: index,
102            name: IncomingName::Text(self.0),
103            value: self.1,
104        }
105    }
106}
107
108impl<'a, S> IntoField<'a, S> for FieldRef<'a> {
109    fn into_field(self, _index: usize) -> IncomingField<'a> {
110        IncomingField {
111            position: self.position,
112            name: IncomingName::Text(self.name),
113            value: self.value,
114        }
115    }
116}
117
118impl<'a, S> IntoField<'a, S> for &FieldRef<'a> {
119    fn into_field(self, index: usize) -> IncomingField<'a> {
120        <FieldRef<'a> as IntoField<'a, S>>::into_field(*self, index)
121    }
122}