make encode_header_value and default_conditional crate-private

This commit is contained in:
2026-10-11 00:12:42 +02:00
parent 4413791b21
commit 3cf2748c30
4 changed files with 20 additions and 21 deletions
+2 -12
View File
@@ -38,18 +38,8 @@ fn encode(encode_buf: &mut String, writer: &mut EmailWriter) {
/// `key` itself is not part of the result: only its length matters, for the length of the first /// `key` itself is not part of the result: only its length matters, for the length of the first
/// line. /// line.
/// ///
/// # Examples /// Pinned by `test_encode_header_value` in `src/tests.rs`.
/// pub(crate) fn encode_header_value(key: &str, value: &str) -> String {
/// ```
/// use cow_mail::header::encode_header_value;
///
/// // Plain text is left alone.
/// assert_eq!(encode_header_value("Subject", "a test"), "a test");
///
/// // Only the words that need it are encoded.
/// assert_eq!(encode_header_value("Subject", "Grüße"), "=?utf-8?b?R3LDvMOfZQ==?=");
/// ```
pub fn encode_header_value(key: &str, value: &str) -> String {
let mut encoded_value = String::new(); let mut encoded_value = String::new();
let line_len = key.len() + ": ".len(); let line_len = key.len() + ": ".len();
let mut writer = EmailWriter::new(&mut encoded_value, line_len, 0, false); let mut writer = EmailWriter::new(&mut encoded_value, line_len, 0, false);
+5 -5
View File
@@ -11,7 +11,7 @@
mod encoding; mod encoding;
mod headers; mod headers;
pub use encoding::encode_header_value; pub(crate) use encoding::encode_header_value;
pub(crate) use headers::build_headers; pub(crate) use headers::build_headers;
pub use headers::{HeaderMap, parse_headers}; pub use headers::{HeaderMap, parse_headers};
@@ -53,8 +53,8 @@ use crate::{CowMailError, offset_in, parse_error};
pub trait Header<'a>: Clone + Display { pub trait Header<'a>: Clone + Display {
/// A new header from a key and a value. /// A new header from a key and a value.
/// ///
/// The value is RFC 2047-encoded and folded as needed — see [`encode_header_value`] — so pass /// The value is RFC 2047-encoded and folded as needed, so pass it as the text it should decode
/// it as the text it should decode to, not pre-encoded. /// to, not pre-encoded.
/// ///
/// # Panics /// # Panics
/// ///
@@ -211,8 +211,8 @@ pub trait Header<'a>: Clone + Display {
} }
struct RFC2045HeaderValue<T> { struct RFC2045HeaderValue<T> {
pub value: T, value: T,
pub params: BTreeMap<T, T>, params: BTreeMap<T, T>,
} }
impl<T: ToString> Display for RFC2045HeaderValue<T> { impl<T: ToString> Display for RFC2045HeaderValue<T> {
+4 -4
View File
@@ -238,7 +238,7 @@ impl ContentType {
/// ///
/// `text/plain` normally, but `message/rfc822` for a part of a `multipart/digest`, per RFC /// `text/plain` normally, but `message/rfc822` for a part of a `multipart/digest`, per RFC
/// 2046 section 5.1.5. Pass whether the part sits in such a digest. /// 2046 section 5.1.5. Pass whether the part sits in such a digest.
pub fn default_conditional(in_multipart_digest: bool) -> Self { pub(crate) fn default_conditional(in_multipart_digest: bool) -> Self {
match in_multipart_digest { match in_multipart_digest {
true => mime::MESSAGE_RFC822, true => mime::MESSAGE_RFC822,
false => mime::TEXT_PLAIN, false => mime::TEXT_PLAIN,
@@ -508,8 +508,8 @@ pub trait Mail<'a, T: Header<'a> + 'a>: HeaderMap<'a, T> {
/// The content type to assume when the part has no `Content-Type` header. /// The content type to assume when the part has no `Content-Type` header.
/// ///
/// Normally `text/plain; charset=us-ascii`, but `message/rfc822` inside a `multipart/digest`. /// Normally `text/plain; charset=us-ascii`, but `message/rfc822` inside a `multipart/digest`,
/// See [`ContentType::default_conditional`]. /// per RFC 2046 section 5.1.5.
fn default_ctype(&self) -> ContentType; fn default_ctype(&self) -> ContentType;
/// The body exactly as it sits in the message, still transfer-encoded. /// The body exactly as it sits in the message, still transfer-encoded.
@@ -808,7 +808,7 @@ pub struct CowMail<'a, H: Header<'a>> {
/// The content type to assume while this part has no `Content-Type` header. /// The content type to assume while this part has no `Content-Type` header.
/// ///
/// Set while parsing, since only then is it known whether the part sits in a /// Set while parsing, since only then is it known whether the part sits in a
/// `multipart/digest`. See [`ContentType::default_conditional`]. /// `multipart/digest` — which makes it `message/rfc822` rather than `text/plain`.
pub default_ctype: ContentType, pub default_ctype: ContentType,
} }
+9
View File
@@ -1,4 +1,5 @@
//use std::io::{Read, Write}; //use std::io::{Read, Write};
use crate::header::encode_header_value;
use crate::{BodyType, CowHeader, CowMail, Header, HeaderMap, Mail, mime}; use crate::{BodyType, CowHeader, CowMail, Header, HeaderMap, Mail, mime};
fn serialize<'a>(mail: &'a CowMail<'a, CowHeader<'a>>) -> Vec<u8> { fn serialize<'a>(mail: &'a CowMail<'a, CowHeader<'a>>) -> Vec<u8> {
@@ -1215,3 +1216,11 @@ fn test_make_mixed_is_case_insensitive() {
assert_eq!(mail.subparts.len(), 1); assert_eq!(mail.subparts.len(), 1);
assert_eq!(String::from_utf8_lossy(&serialize(&mail)), raw); assert_eq!(String::from_utf8_lossy(&serialize(&mail)), raw);
} }
// Was a doc test on `encode_header_value` before it became crate-private.
// A word of allowed bytes is written as it stands; the rest is RFC 2047-encoded.
#[test]
fn test_encode_header_value() {
assert_eq!(encode_header_value("Subject", "a test"), "a test");
assert_eq!(encode_header_value("Subject", "Grüße"), "=?utf-8?b?R3LDvMOfZQ==?=");
}