Repository: duesee/imap-codec (language: python)

Issue:
chore: Don't (always) export nom parsers.



Discussion / hints:

Fix patch:
diff --git a/src/auth.rs b/src/auth.rs
index 0e9c180f..47a695fe 100644
--- a/src/auth.rs
+++ b/src/auth.rs
@@ -19,7 +19,7 @@ use crate::{
 /// `auth-type = atom`
 ///
 /// Note: Defined by \[SASL\]
-pub fn auth_type(input: &[u8]) -> IMAPResult<&[u8], AuthMechanism> {
+pub(crate) fn auth_type(input: &[u8]) -> IMAPResult<&[u8], AuthMechanism> {
     let (rem, atom) = atom(input)?;
 
     Ok((rem, AuthMechanism::from(atom)))
@@ -35,7 +35,7 @@ pub fn auth_type(input: &[u8]) -> IMAPResult<&[u8], AuthMechanism> {
 ///                CRLF is additionally parsed in this parser.
 ///                FIXME: Multiline base64 currently does not work.
 /// ```
-pub fn authenticate_data(input: &[u8]) -> IMAPResult<&[u8], AuthenticateData> {
+pub(crate) fn authenticate_data(input: &[u8]) -> IMAPResult<&[u8], AuthenticateData> {
     map(terminated(base64, crlf), |data| {
         AuthenticateData(Secret::new(data))
     })(input) // FIXME: many0 deleted
diff --git a/src/body.rs b/src/body.rs
index 0b9e7eca..670189a1 100644
--- a/src/body.rs
+++ b/src/body.rs
@@ -21,7 +21,9 @@ use crate::{
 ///
 /// Note: This parser is recursively defined. Thus, in order to not overflow the stack,
 /// it is needed to limit how may recursions are allowed. (8 should suffice).
-pub fn body(remaining_recursions: usize) -> impl Fn(&[u8]) -> IMAPResult<&[u8], BodyStructure> {
+pub(crate) fn body(
+    remaining_recursions: usize,
+) -> impl Fn(&[u8]) -> IMAPResult<&[u8], BodyStructure> {
     move |input: &[u8]| body_limited(input, remaining_recursions)
 }
 
@@ -91,7 +93,7 @@ fn body_type_1part_limited<'a>(
 /// `body-type-basic = media-basic SP body-fields`
 ///
 /// MESSAGE subtype MUST NOT be "RFC822"
-pub fn body_type_basic(input: &[u8]) -> IMAPResult<&[u8], (BasicFields, SpecificFields)> {
+pub(crate) fn body_type_basic(input: &[u8]) -> IMAPResult<&[u8], (BasicFields, SpecificFields)> {
     let mut parser = tuple((media_basic, sp, body_fields));
 
     let (remaining, ((type_, subtype), _, basic)) = parser(input)?;
@@ -160,7 +162,7 @@ fn body_type_msg_limited<'a>(
 /// `body-type-text = media-text SP
 ///                   body-fields SP
 ///                   body-fld-lines`
-pub fn body_type_text(input: &[u8]) -> IMAPResult<&[u8], (BasicFields, SpecificFields)> {
+pub(crate) fn body_type_text(input: &[u8]) -> IMAPResult<&[u8], (BasicFields, SpecificFields)> {
     let mut parser = tuple((media_text, sp, body_fields, sp, body_fld_lines));
 
     let (remaining, (subtype, _, basic, _, number_of_lines)) = parser(input)?;
@@ -182,7 +184,7 @@ pub fn body_type_text(input: &[u8]) -> IMAPResult<&[u8], (BasicFields, SpecificF
 ///                body-fld-desc SP
 ///                body-fld-enc SP
 ///                body-fld-octets`
-pub fn body_fields(input: &[u8]) -> IMAPResult<&[u8], BasicFields> {
+pub(crate) fn body_fields(input: &[u8]) -> IMAPResult<&[u8], BasicFields> {
     let mut parser = tuple((
         body_fld_param,
         sp,
@@ -214,7 +216,7 @@ pub fn body_fields(input: &[u8]) -> IMAPResult<&[u8], BasicFields> {
 ///                   string SP
 ///                   string *(SP string SP string)
 ///                   ")" / nil`
-pub fn body_fld_param(input: &[u8]) -> IMAPResult<&[u8], Vec<(IString, IString)>> {
+pub(crate) fn body_fld_param(input: &[u8]) -> IMAPResult<&[u8], Vec<(IString, IString)>> {
     let mut parser = alt((
         delimited(
             tag(b"("),
@@ -234,13 +236,13 @@ pub fn body_fld_param(input: &[u8]) -> IMAPResult<&[u8], Vec<(IString, IString)>
 
 #[inline]
 /// `body-fld-id = nstring`
-pub fn body_fld_id(input: &[u8]) -> IMAPResult<&[u8], NString> {
+pub(crate) fn body_fld_id(input: &[u8]) -> IMAPResult<&[u8], NString> {
     nstring(input)
 }
 
 #[inline]
 /// `body-fld-desc = nstring`
-pub fn body_fld_desc(input: &[u8]) -> IMAPResult<&[u8], NString> {
+pub(crate) fn body_fld_desc(input: &[u8]) -> IMAPResult<&[u8], NString> {
     nstring(input)
 }
 
@@ -260,19 +262,19 @@ pub fn body_fld_desc(input: &[u8]) -> IMAPResult<&[u8], NString> {
 /// `body-fld-enc = string`
 ///
 /// TODO: why the special case?
-pub fn body_fld_enc(input: &[u8]) -> IMAPResult<&[u8], IString> {
+pub(crate) fn body_fld_enc(input: &[u8]) -> IMAPResult<&[u8], IString> {
     string(input)
 }
 
 #[inline]
 /// `body-fld-octets = number`
-pub fn body_fld_octets(input: &[u8]) -> IMAPResult<&[u8], u32> {
+pub(crate) fn body_fld_octets(input: &[u8]) -> IMAPResult<&[u8], u32> {
     number(input)
 }
 
 #[inline]
 /// `body-fld-lines = number`
-pub fn body_fld_lines(input: &[u8]) -> IMAPResult<&[u8], u32> {
+pub(crate) fn body_fld_lines(input: &[u8]) -> IMAPResult<&[u8], u32> {
     number(input)
 }
 
@@ -286,7 +288,7 @@ pub fn body_fld_lines(input: &[u8]) -> IMAPResult<&[u8], u32> {
 /// ```
 ///
 /// Note: MUST NOT be returned on non-extensible "BODY" fetch.
-pub fn body_ext_1part(input: &[u8]) -> IMAPResult<&[u8], SinglePartExtensionData> {
+pub(crate) fn body_ext_1part(input: &[u8]) -> IMAPResult<&[u8], SinglePartExtensionData> {
     map(
         tuple((
             body_fld_md5,
@@ -319,13 +321,15 @@ pub fn body_ext_1part(input: &[u8]) -> IMAPResult<&[u8], SinglePartExtensionData
 
 #[inline]
 /// `body-fld-md5 = nstring`
-pub fn body_fld_md5(input: &[u8]) -> IMAPResult<&[u8], NString> {
+pub(crate) fn body_fld_md5(input: &[u8]) -> IMAPResult<&[u8], NString> {
     nstring(input)
 }
 
 /// `body-fld-dsp = "(" string SP body-fld-param ")" / nil`
 #[allow(clippy::type_complexity)]
-pub fn body_fld_dsp(input: &[u8]) -> IMAPResult<&[u8], Option<(IString, Vec<(IString, IString)>)>> {
+pub(crate) fn body_fld_dsp(
+    input: &[u8],
+) -> IMAPResult<&[u8], Option<(IString, Vec<(IString, IString)>)>> {
     alt((
         delimited(
             tag(b"("),
@@ -340,7 +344,7 @@ pub fn body_fld_dsp(input: &[u8]) -> IMAPResult<&[u8], Option<(IString, Vec<(ISt
 }
 
 /// `body-fld-lang = nstring / "(" string *(SP string) ")"`
-pub fn body_fld_lang(input: &[u8]) -> IMAPResult<&[u8], Vec<IString>> {
+pub(crate) fn body_fld_lang(input: &[u8]) -> IMAPResult<&[u8], Vec<IString>> {
     alt((
         map(nstring, |nstring| match nstring.0 {
             Some(item) => vec![item],
@@ -352,7 +356,7 @@ pub fn body_fld_lang(input: &[u8]) -> IMAPResult<&[u8], Vec<IString>> {
 
 #[inline]
 /// `body-fld-loc = nstring`
-pub fn body_fld_loc(input: &[u8]) -> IMAPResult<&[u8], NString> {
+pub(crate) fn body_fld_loc(input: &[u8]) -> IMAPResult<&[u8], NString> {
     nstring(input)
 }
 
@@ -370,7 +374,7 @@ pub fn body_fld_loc(input: &[u8]) -> IMAPResult<&[u8], NString> {
 ///
 /// Note: This parser is recursively defined. Thus, in order to not overflow the stack,
 /// it is needed to limit how may recursions are allowed. (8 should suffice).
-pub fn body_extension(
+pub(crate) fn body_extension(
     remaining_recursions: usize,
 ) -> impl Fn(&[u8]) -> IMAPResult<&[u8], BodyExtension> {
     move |input: &[u8]| body_extension_limited(input, remaining_recursions)
@@ -447,7 +451,7 @@ fn body_type_mpart_limited(
 /// ```
 ///
 /// Note: MUST NOT be returned on non-extensible "BODY" fetch.
-pub fn body_ext_mpart(input: &[u8]) -> IMAPResult<&[u8], MultiPartExtensionData> {
+pub(crate) fn body_ext_mpart(input: &[u8]) -> IMAPResult<&[u8], MultiPartExtensionData> {
     map(
         tuple((
             body_fld_param,
@@ -502,7 +506,7 @@ pub fn body_ext_mpart(input: &[u8]) -> IMAPResult<&[u8], MultiPartExtensionData>
 /// TODO: Why the special case?
 ///
 /// Defined in [MIME-IMT]
-pub fn media_basic(input: &[u8]) -> IMAPResult<&[u8], (IString, IString)> {
+pub(crate) fn media_basic(input: &[u8]) -> IMAPResult<&[u8], (IString, IString)> {
     let mut parser = tuple((string, sp, media_subtype));
 
     let (remaining, (type_, _, subtype)) = parser(input)?;
@@ -514,7 +518,7 @@ pub fn media_basic(input: &[u8]) -> IMAPResult<&[u8], (IString, IString)> {
 /// `media-subtype = string`
 ///
 /// Defined in [MIME-IMT]
-pub fn media_subtype(input: &[u8]) -> IMAPResult<&[u8], IString> {
+pub(crate) fn media_subtype(input: &[u8]) -> IMAPResult<&[u8], IString> {
     string(input)
 }
 
@@ -529,7 +533,7 @@ pub fn media_subtype(input: &[u8]) -> IMAPResult<&[u8], IString> {
 /// Defined in [MIME-IMT]
 ///
 /// "message" "rfc822" basic specific-for-message-rfc822 extension
-pub fn media_message(input: &[u8]) -> IMAPResult<&[u8], &[u8]> {
+pub(crate) fn media_message(input: &[u8]) -> IMAPResult<&[u8], &[u8]> {
     tag_no_case(b"\"MESSAGE\" \"RFC822\"")(input)
 }
 
@@ -538,7 +542,7 @@ pub fn media_message(input: &[u8]) -> IMAPResult<&[u8], &[u8]> {
 /// Defined in [MIME-IMT]
 ///
 /// "text" "?????" basic specific-for-text extension
-pub fn media_text(input: &[u8]) -> IMAPResult<&[u8], IString> {
+pub(crate) fn media_text(input: &[u8]) -> IMAPResult<&[u8], IString> {
     let mut parser = preceded(tag_no_case(b"\"TEXT\" "), media_subtype);
 
     let (remaining, media_subtype) = parser(input)?;
diff --git a/src/codec/decode.rs b/src/codec/decode.rs
index c3be8a36..09374b40 100644
--- a/src/codec/decode.rs
+++ b/src/codec/decode.rs
@@ -12,18 +12,19 @@ use crate::{
 };
 
 /// An extended version of [`nom::IResult`].
-pub type IMAPResult<I, O> = Result<(I, O), nom::Err<IMAPParseError<I>>>;
+pub(crate) type IMAPResult<I, O> = Result<(I, O), nom::Err<IMAPParseError<I>>>;
 
 /// An extended version of [`nom::error::Error`].
 #[derive(Debug)]
-pub struct IMAPParseError<I> {
+pub(crate) struct IMAPParseError<I> {
+    #[allow(unused)]
     pub input: I,
     pub kind: IMAPErrorKind,
 }
 
 /// An extended version of [`nom::error::ErrorKind`].
 #[derive(Debug)]
-pub enum IMAPErrorKind {
+pub(crate) enum IMAPErrorKind {
     Literal {
         length: u32,
         #[cfg(feature = "ext_literal")]
diff --git a/src/command.rs b/src/command.rs
index 5e26afd6..8473413f 100644
--- a/src/command.rs
+++ b/src/command.rs
@@ -50,7 +50,7 @@ use crate::{
 ///                     command-nonauth /
 ///                     command-select
 ///                   ) CRLF`
-pub fn command(input: &[u8]) -> IMAPResult<&[u8], Command> {
+pub(crate) fn command(input: &[u8]) -> IMAPResult<&[u8], Command> {
     let mut parser = tuple((
         tag_imap,
         sp,
@@ -68,7 +68,7 @@ pub fn command(input: &[u8]) -> IMAPResult<&[u8], Command> {
 /// `command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command`
 ///
 /// Note: Valid in all states
-pub fn command_any(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn command_any(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     alt((
         value(CommandBody::Capability, tag_no_case(b"CAPABILITY")),
         value(CommandBody::Logout, tag_no_case(b"LOGOUT")),
@@ -95,7 +95,7 @@ pub fn command_any(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 ///                 compress ; RFC 4978`
 ///
 /// Note: Valid only in Authenticated or Selected state
-pub fn command_auth(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn command_auth(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     alt((
         append,
         create,
@@ -124,7 +124,7 @@ pub fn command_auth(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 }
 
 /// `append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP literal`
-pub fn append(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn append(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((
         tag_no_case(b"APPEND"),
         sp,
@@ -151,7 +151,7 @@ pub fn append(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 /// `create = "CREATE" SP mailbox`
 ///
 /// Note: Use of INBOX gives a NO error
-pub fn create(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn create(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((tag_no_case(b"CREATE"), sp, mailbox));
 
     let (remaining, (_, _, mailbox)) = parser(input)?;
@@ -162,7 +162,7 @@ pub fn create(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 /// `delete = "DELETE" SP mailbox`
 ///
 /// Note: Use of INBOX gives a NO error
-pub fn delete(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn delete(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((tag_no_case(b"DELETE"), sp, mailbox));
 
     let (remaining, (_, _, mailbox)) = parser(input)?;
@@ -171,7 +171,7 @@ pub fn delete(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 }
 
 /// `examine = "EXAMINE" SP mailbox`
-pub fn examine(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn examine(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((tag_no_case(b"EXAMINE"), sp, mailbox));
 
     let (remaining, (_, _, mailbox)) = parser(input)?;
@@ -180,7 +180,7 @@ pub fn examine(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 }
 
 /// `list = "LIST" SP mailbox SP list-mailbox`
-pub fn list(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn list(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((tag_no_case(b"LIST"), sp, mailbox, sp, list_mailbox));
 
     let (remaining, (_, _, reference, _, mailbox_wildcard)) = parser(input)?;
@@ -195,7 +195,7 @@ pub fn list(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 }
 
 /// `lsub = "LSUB" SP mailbox SP list-mailbox`
-pub fn lsub(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn lsub(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((tag_no_case(b"LSUB"), sp, mailbox, sp, list_mailbox));
 
     let (remaining, (_, _, reference, _, mailbox_wildcard)) = parser(input)?;
@@ -212,7 +212,7 @@ pub fn lsub(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 /// `rename = "RENAME" SP mailbox SP mailbox`
 ///
 /// Note: Use of INBOX as a destination gives a NO error
-pub fn rename(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn rename(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((tag_no_case(b"RENAME"), sp, mailbox, sp, mailbox));
 
     let (remaining, (_, _, mailbox, _, new_mailbox)) = parser(input)?;
@@ -227,7 +227,7 @@ pub fn rename(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 }
 
 /// `select = "SELECT" SP mailbox`
-pub fn select(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn select(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((tag_no_case(b"SELECT"), sp, mailbox));
 
     let (remaining, (_, _, mailbox)) = parser(input)?;
@@ -236,7 +236,7 @@ pub fn select(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 }
 
 /// `status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")"`
-pub fn status(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn status(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((
         tag_no_case(b"STATUS"),
         sp,
@@ -257,7 +257,7 @@ pub fn status(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 }
 
 /// `subscribe = "SUBSCRIBE" SP mailbox`
-pub fn subscribe(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn subscribe(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((tag_no_case(b"SUBSCRIBE"), sp, mailbox));
 
     let (remaining, (_, _, mailbox)) = parser(input)?;
@@ -266,7 +266,7 @@ pub fn subscribe(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 }
 
 /// `unsubscribe = "UNSUBSCRIBE" SP mailbox`
-pub fn unsubscribe(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn unsubscribe(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((tag_no_case(b"UNSUBSCRIBE"), sp, mailbox));
 
     let (remaining, (_, _, mailbox)) = parser(input)?;
@@ -279,7 +279,7 @@ pub fn unsubscribe(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 /// `command-nonauth = login / authenticate / "STARTTLS"`
 ///
 /// Note: Valid only when in Not Authenticated state
-pub fn command_nonauth(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn command_nonauth(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = alt((
         login,
         #[cfg(not(feature = "ext_sasl_ir"))]
@@ -303,7 +303,7 @@ pub fn command_nonauth(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 }
 
 /// `login = "LOGIN" SP userid SP password`
-pub fn login(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn login(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((tag_no_case(b"LOGIN"), sp, userid, sp, password));
 
     let (remaining, (_, _, username, _, password)) = parser(input)?;
@@ -319,13 +319,13 @@ pub fn login(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 
 #[inline]
 /// `userid = astring`
-pub fn userid(input: &[u8]) -> IMAPResult<&[u8], AString> {
+pub(crate) fn userid(input: &[u8]) -> IMAPResult<&[u8], AString> {
     astring(input)
 }
 
 #[inline]
 /// `password = astring`
-pub fn password(input: &[u8]) -> IMAPResult<&[u8], AString> {
+pub(crate) fn password(input: &[u8]) -> IMAPResult<&[u8], AString> {
     astring(input)
 }
 
@@ -339,7 +339,7 @@ pub fn password(input: &[u8]) -> IMAPResult<&[u8], AString> {
 ///                CRLF is parsed by upper command parser.
 /// ```
 #[cfg(not(feature = "ext_sasl_ir"))]
-pub fn authenticate(input: &[u8]) -> IMAPResult<&[u8], AuthMechanism> {
+pub(crate) fn authenticate(input: &[u8]) -> IMAPResult<&[u8], AuthMechanism> {
     let mut parser = preceded(tag_no_case(b"AUTHENTICATE "), auth_type);
 
     let (remaining, auth_type) = parser(input)?;
@@ -364,7 +364,7 @@ pub fn authenticate(input: &[u8]) -> IMAPResult<&[u8], AuthMechanism> {
 #[cfg(feature = "ext_sasl_ir")]
 #[cfg_attr(docsrs, doc(cfg(feature = "ext_sasl_ir")))]
 #[allow(clippy::type_complexity)]
-pub fn authenticate_sasl_ir(
+pub(crate) fn authenticate_sasl_ir(
     input: &[u8],
 ) -> IMAPResult<&[u8], (AuthMechanism, Option<Secret<Cow<[u8]>>>)> {
     let mut parser = tuple((
@@ -398,7 +398,7 @@ pub fn authenticate_sasl_ir(
 ///                   search`
 ///
 /// Note: Valid only when in Selected state
-pub fn command_select(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn command_select(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     alt((
         value(CommandBody::Check, tag_no_case(b"CHECK")),
         value(CommandBody::Close, tag_no_case(b"CLOSE")),
@@ -416,7 +416,7 @@ pub fn command_select(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 }
 
 /// `copy = "COPY" SP sequence-set SP mailbox`
-pub fn copy(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn copy(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((tag_no_case(b"COPY"), sp, sequence_set, sp, mailbox));
 
     let (remaining, (_, _, sequence_set, _, mailbox)) = parser(input)?;
@@ -435,7 +435,7 @@ pub fn copy(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 ///                                      "FULL" /
 ///                                      "FAST" /
 ///                                      fetch-att / "(" fetch-att *(SP fetch-att) ")")`
-pub fn fetch(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn fetch(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((
         tag_no_case(b"FETCH"),
         sp,
@@ -477,7 +477,7 @@ pub fn fetch(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 }
 
 /// `store = "STORE" SP sequence-set SP store-att-flags`
-pub fn store(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn store(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((tag_no_case(b"STORE"), sp, sequence_set, sp, store_att_flags));
 
     let (remaining, (_, _, sequence_set, _, (kind, response, flags))) = parser(input)?;
@@ -495,7 +495,9 @@ pub fn store(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 }
 
 /// `store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP (flag-list / (flag *(SP flag)))`
-pub fn store_att_flags(input: &[u8]) -> IMAPResult<&[u8], (StoreType, StoreResponse, Vec<Flag>)> {
+pub(crate) fn store_att_flags(
+    input: &[u8],
+) -> IMAPResult<&[u8], (StoreType, StoreResponse, Vec<Flag>)> {
     let mut parser = tuple((
         tuple((
             map(
@@ -526,7 +528,7 @@ pub fn store_att_flags(input: &[u8]) -> IMAPResult<&[u8], (StoreType, StoreRespo
 /// `uid = "UID" SP (copy / fetch / search / store)`
 ///
 /// Note: Unique identifiers used instead of message sequence numbers
-pub fn uid(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn uid(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((
         tag_no_case(b"UID"),
         sp,
diff --git a/src/core.rs b/src/core.rs
index 7c5af27e..fcc3b18b 100644
--- a/src/core.rs
+++ b/src/core.rs
@@ -30,7 +30,7 @@ use crate::{
 /// `number = 1*DIGIT`
 ///
 /// Unsigned 32-bit integer (0 <= n < 4,294,967,296)
-pub fn number(input: &[u8]) -> IMAPResult<&[u8], u32> {
+pub(crate) fn number(input: &[u8]) -> IMAPResult<&[u8], u32> {
     map_res(
         // # Safety
         //
@@ -49,7 +49,7 @@ pub fn number(input: &[u8]) -> IMAPResult<&[u8], u32> {
 /// Defined in RFC 9051
 #[cfg(feature = "ext_quota")]
 #[cfg_attr(docsrs, doc(cfg(feature = "ext_quota")))]
-pub fn number64(input: &[u8]) -> IMAPResult<&[u8], u64> {
+pub(crate) fn number64(input: &[u8]) -> IMAPResult<&[u8], u64> {
     map_res(
         // # Safety
         //
@@ -62,7 +62,7 @@ pub fn number64(input: &[u8]) -> IMAPResult<&[u8], u64> {
 /// `nz-number = digit-nz *DIGIT`
 ///
 /// Non-zero unsigned 32-bit integer (0 < n < 4,294,967,296)
-pub fn nz_number(input: &[u8]) -> IMAPResult<&[u8], NonZeroU32> {
+pub(crate) fn nz_number(input: &[u8]) -> IMAPResult<&[u8], NonZeroU32> {
     map_res(number, NonZeroU32::try_from)(input)
 }
 
@@ -76,7 +76,7 @@ pub fn nz_number(input: &[u8]) -> IMAPResult<&[u8], NonZeroU32> {
 // ----- string -----
 
 /// `string = quoted / literal`
-pub fn string(input: &[u8]) -> IMAPResult<&[u8], IString> {
+pub(crate) fn string(input: &[u8]) -> IMAPResult<&[u8], IString> {
     alt((map(quoted, IString::Quoted), map(literal, IString::Literal)))(input)
 }
 
@@ -84,7 +84,7 @@ pub fn string(input: &[u8]) -> IMAPResult<&[u8], IString> {
 ///
 /// This function only allocates a new String, when needed, i.e. when
 /// quoted chars need to be replaced.
-pub fn quoted(input: &[u8]) -> IMAPResult<&[u8], Quoted> {
+pub(crate) fn quoted(input: &[u8]) -> IMAPResult<&[u8], Quoted> {
     let mut parser = tuple((
         dquote,
         map(
@@ -107,7 +107,7 @@ pub fn quoted(input: &[u8]) -> IMAPResult<&[u8], Quoted> {
 }
 
 /// `QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> / "\" quoted-specials`
-pub fn quoted_char(input: &[u8]) -> IMAPResult<&[u8], QuotedChar> {
+pub(crate) fn quoted_char(input: &[u8]) -> IMAPResult<&[u8], QuotedChar> {
     map(
         alt((
             map(
@@ -134,7 +134,7 @@ pub(crate) fn is_any_text_char_except_quoted_specials(byte: u8) -> bool {
 }
 
 /// `quoted-specials = DQUOTE / "\"`
-pub fn is_quoted_specials(byte: u8) -> bool {
+pub(crate) fn is_quoted_specials(byte: u8) -> bool {
     byte == b'"' || byte == b'\\'
 }
 
@@ -153,7 +153,7 @@ pub fn is_quoted_specials(byte: u8) -> bool {
 /// literal8 = <defined in RFC 4466>
 /// ```
 /// -- <https://datatracker.ietf.org/doc/html/rfc7888#section-8>
-pub fn literal(input: &[u8]) -> IMAPResult<&[u8], Literal> {
+pub(crate) fn literal(input: &[u8]) -> IMAPResult<&[u8], Literal> {
     #[cfg(not(feature = "ext_literal"))]
     let (remaining, length) = terminated(delimited(tag(b"{"), number, tag(b"}")), crlf)(input)?;
 
@@ -214,7 +214,7 @@ pub fn literal(input: &[u8]) -> IMAPResult<&[u8], Literal> {
 // ----- astring ----- atom (roughly) or string
 
 /// `astring = 1*ASTRING-CHAR / string`
-pub fn astring(input: &[u8]) -> IMAPResult<&[u8], AString> {
+pub(crate) fn astring(input: &[u8]) -> IMAPResult<&[u8], AString> {
     alt((
         map(take_while1(is_astring_char), |bytes: &[u8]| {
             // # Safety
@@ -231,17 +231,17 @@ pub fn astring(input: &[u8]) -> IMAPResult<&[u8], AString> {
 }
 
 /// `ASTRING-CHAR = ATOM-CHAR / resp-specials`
-pub fn is_astring_char(i: u8) -> bool {
+pub(crate) fn is_astring_char(i: u8) -> bool {
     is_atom_char(i) || is_resp_specials(i)
 }
 
 /// `ATOM-CHAR = <any CHAR except atom-specials>`
-pub fn is_atom_char(b: u8) -> bool {
+pub(crate) fn is_atom_char(b: u8) -> bool {
     is_char(b) && !is_atom_specials(b)
 }
 
 /// `atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / quoted-specials / resp-specials`
-pub fn is_atom_specials(i: u8) -> bool {
+pub(crate) fn is_atom_specials(i: u8) -> bool {
     match i {
         b'(' | b')' | b'{' | b' ' => true,
         c if is_ctl(c) => true,
@@ -254,12 +254,12 @@ pub fn is_atom_specials(i: u8) -> bool {
 
 #[inline]
 /// `resp-specials = "]"`
-pub fn is_resp_specials(i: u8) -> bool {
+pub(crate) fn is_resp_specials(i: u8) -> bool {
     i == b']'
 }
 
 /// `atom = 1*ATOM-CHAR`
-pub fn atom(input: &[u8]) -> IMAPResult<&[u8], Atom> {
+pub(crate) fn atom(input: &[u8]) -> IMAPResult<&[u8], Atom> {
     let parser = take_while1(is_atom_char);
 
     let (remaining, parsed_atom) = parser(input)?;
@@ -278,7 +278,7 @@ pub fn atom(input: &[u8]) -> IMAPResult<&[u8], Atom> {
 // ----- nstring ----- nil or string
 
 /// `nstring = string / nil`
-pub fn nstring(input: &[u8]) -> IMAPResult<&[u8], NString> {
+pub(crate) fn nstring(input: &[u8]) -> IMAPResult<&[u8], NString> {
     alt((
         map(string, |item| NString(Some(item))),
         map(nil, |_| NString(None)),
@@ -287,14 +287,14 @@ pub fn nstring(input: &[u8]) -> IMAPResult<&[u8], NString> {
 
 #[inline]
 /// `nil = "NIL"`
-pub fn nil(input: &[u8]) -> IMAPResult<&[u8], &[u8]> {
+pub(crate) fn nil(input: &[u8]) -> IMAPResult<&[u8], &[u8]> {
     tag_no_case(b"NIL")(input)
 }
 
 // ----- text -----
 
 /// `text = 1*TEXT-CHAR`
-pub fn text(input: &[u8]) -> IMAPResult<&[u8], Text> {
+pub(crate) fn text(input: &[u8]) -> IMAPResult<&[u8], Text> {
     map(take_while1(is_text_char), |bytes|
         // # Safety
         // 
@@ -308,14 +308,14 @@ pub fn text(input: &[u8]) -> IMAPResult<&[u8], Text> {
 /// Note: This was `<any CHAR except CR and LF>` before.
 ///
 /// Note: We also exclude `[` and `]` due to the possibility to misuse this as a `Code`.
-pub fn is_text_char(c: u8) -> bool {
+pub(crate) fn is_text_char(c: u8) -> bool {
     matches!(c, 0x01..=0x09 | 0x0b..=0x0c | 0x0e..=0x5a | 0x5c | 0x5e..=0x7f)
 }
 
 // ----- base64 -----
 
 /// `base64 = *(4base64-char) [base64-terminal]`
-pub fn base64(input: &[u8]) -> IMAPResult<&[u8], Vec<u8>> {
+pub(crate) fn base64(input: &[u8]) -> IMAPResult<&[u8], Vec<u8>> {
     map_res(
         recognize(tuple((
             take_while(is_base64_char),
@@ -326,7 +326,7 @@ pub fn base64(input: &[u8]) -> IMAPResult<&[u8], Vec<u8>> {
 }
 
 /// `base64-char = ALPHA / DIGIT / "+" / "/" ; Case-sensitive`
-pub fn is_base64_char(i: u8) -> bool {
+pub(crate) fn is_base64_char(i: u8) -> bool {
     is_alpha(i) || is_digit(i) || i == b'+' || i == b'/'
 }
 
@@ -337,14 +337,14 @@ pub fn is_base64_char(i: u8) -> bool {
 /// `charset = atom / quoted`
 ///
 /// Note: see errata id: 261
-pub fn charset(input: &[u8]) -> IMAPResult<&[u8], Charset> {
+pub(crate) fn charset(input: &[u8]) -> IMAPResult<&[u8], Charset> {
     alt((map(atom, Charset::Atom), map(quoted, Charset::Quoted)))(input)
 }
 
 // ----- tag -----
 
 /// `tag = 1*<any ASTRING-CHAR except "+">`
-pub fn tag_imap(input: &[u8]) -> IMAPResult<&[u8], Tag> {
+pub(crate) fn tag_imap(input: &[u8]) -> IMAPResult<&[u8], Tag> {
     map(take_while1(|b| is_astring_char(b) && b != b'+'), |val| {
         // # Safety
         //
diff --git a/src/datetime.rs b/src/datetime.rs
index 815fcf68..6b4d4377 100644
--- a/src/datetime.rs
+++ b/src/datetime.rs
@@ -22,14 +22,14 @@ use crate::codec::{IMAPErrorKind, IMAPParseError, IMAPResult};
 /// ```abnf
 /// date = date-text / DQUOTE date-text DQUOTE
 /// ```
-pub fn date(input: &[u8]) -> IMAPResult<&[u8], Option<NaiveDate>> {
+pub(crate) fn date(input: &[u8]) -> IMAPResult<&[u8], Option<NaiveDate>> {
     alt((date_text, delimited(dquote, date_text, dquote)))(input)
 }
 
 /// ```abnf
 /// date-text = date-day "-" date-month "-" date-year
 /// ```
-pub fn date_text(input: &[u8]) -> IMAPResult<&[u8], Option<NaiveDate>> {
+pub(crate) fn date_text(input: &[u8]) -> IMAPResult<&[u8], Option<NaiveDate>> {
     let mut parser = tuple((date_day, tag(b"-"), date_month, tag(b"-"), date_year));
 
     let (remaining, (d, _, m, _, y)) = parser(input)?;
@@ -45,7 +45,7 @@ pub fn date_text(input: &[u8]) -> IMAPResult<&[u8], Option<NaiveDate>> {
 /// ```abnf
 /// date-day = 1*2DIGIT
 /// ```
-pub fn date_day(input: &[u8]) -> IMAPResult<&[u8], u8> {
+pub(crate) fn date_day(input: &[u8]) -> IMAPResult<&[u8], u8> {
     digit_1_2(input)
 }
 
@@ -54,7 +54,7 @@ pub fn date_day(input: &[u8]) -> IMAPResult<&[u8], u8> {
 ///              "May" / "Jun" / "Jul" / "Aug" /
 ///              "Sep" / "Oct" / "Nov" / "Dec"
 /// ```
-pub fn date_month(input: &[u8]) -> IMAPResult<&[u8], u8> {
+pub(crate) fn date_month(input: &[u8]) -> IMAPResult<&[u8], u8> {
     alt((
         value(1, tag_no_case(b"Jan")),
         value(2, tag_no_case(b"Feb")),
@@ -74,7 +74,7 @@ pub fn date_month(input: &[u8]) -> IMAPResult<&[u8], u8> {
 /// ```abnf
 /// date-year = 4DIGIT
 /// ```
-pub fn date_year(input: &[u8]) -> IMAPResult<&[u8], u16> {
+pub(crate) fn date_year(input: &[u8]) -> IMAPResult<&[u8], u16> {
     digit_4(input)
 }
 
@@ -83,7 +83,7 @@ pub fn date_year(input: &[u8]) -> IMAPResult<&[u8], u16> {
 /// ```abnf
 /// time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
 /// ```
-pub fn time(input: &[u8]) -> IMAPResult<&[u8], Option<NaiveTime>> {
+pub(crate) fn time(input: &[u8]) -> IMAPResult<&[u8], Option<NaiveTime>> {
     let mut parser = tuple((digit_2, tag(b":"), digit_2, tag(b":"), digit_2));
 
     let (remaining, (h, _, m, _, s)) = parser(input)?;
@@ -101,7 +101,7 @@ pub fn time(input: &[u8]) -> IMAPResult<&[u8], Option<NaiveTime>> {
 ///              zone
 ///             DQUOTE
 /// ```
-pub fn date_time(input: &[u8]) -> IMAPResult<&[u8], DateTime> {
+pub(crate) fn date_time(input: &[u8]) -> IMAPResult<&[u8], DateTime> {
     let mut parser = delimited(
         dquote,
         tuple((
@@ -147,7 +147,7 @@ pub fn date_time(input: &[u8]) -> IMAPResult<&[u8], DateTime> {
 /// ```abnf
 /// date-day-fixed = (SP DIGIT) / 2DIGIT
 /// ```
-pub fn date_day_fixed(input: &[u8]) -> IMAPResult<&[u8], u8> {
+pub(crate) fn date_day_fixed(input: &[u8]) -> IMAPResult<&[u8], u8> {
     alt((
         map(
             preceded(sp, take_while_m_n(1, 1, is_digit)),
@@ -166,7 +166,7 @@ pub fn date_day_fixed(input: &[u8]) -> IMAPResult<&[u8], u8> {
 /// ```abnf
 /// zone = ("+" / "-") 4DIGIT
 /// ```
-pub fn zone(input: &[u8]) -> IMAPResult<&[u8], Option<FixedOffset>> {
+pub(crate) fn zone(input: &[u8]) -> IMAPResult<&[u8], Option<FixedOffset>> {
     let mut parser = tuple((alt((char('+'), char('-'))), digit_2, digit_2));
 
     let (remaining, (sign, hh, mm)) = parser(input)?;
diff --git a/src/envelope.rs b/src/envelope.rs
index c2bd876d..a50afaf9 100644
--- a/src/envelope.rs
+++ b/src/envelope.rs
@@ -30,7 +30,7 @@ use crate::{
 ///              env-message-id
 ///            ")"
 /// ```
-pub fn envelope(input: &[u8]) -> IMAPResult<&[u8], Envelope> {
+pub(crate) fn envelope(input: &[u8]) -> IMAPResult<&[u8], Envelope> {
     let mut parser = delimited(
         tag(b"("),
         tuple((
@@ -101,18 +101,18 @@ pub fn envelope(input: &[u8]) -> IMAPResult<&[u8], Envelope> {
 
 #[inline]
 /// `env-date = nstring`
-pub fn env_date(input: &[u8]) -> IMAPResult<&[u8], NString> {
+pub(crate) fn env_date(input: &[u8]) -> IMAPResult<&[u8], NString> {
     nstring(input)
 }
 
 #[inline]
 /// `env-subject = nstring`
-pub fn env_subject(input: &[u8]) -> IMAPResult<&[u8], NString> {
+pub(crate) fn env_subject(input: &[u8]) -> IMAPResult<&[u8], NString> {
     nstring(input)
 }
 
 /// `env-from = "(" 1*address ")" / nil`
-pub fn env_from(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
+pub(crate) fn env_from(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
     alt((
         delimited(tag(b"("), many1(address), tag(b")")),
         map(nil, |_| Vec::new()),
@@ -120,7 +120,7 @@ pub fn env_from(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
 }
 
 /// `env-sender = "(" 1*address ")" / nil`
-pub fn env_sender(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
+pub(crate) fn env_sender(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
     alt((
         delimited(tag(b"("), many1(address), tag(b")")),
         map(nil, |_| Vec::new()),
@@ -128,7 +128,7 @@ pub fn env_sender(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
 }
 
 /// `env-reply-to = "(" 1*address ")" / nil`
-pub fn env_reply_to(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
+pub(crate) fn env_reply_to(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
     alt((
         delimited(tag(b"("), many1(address), tag(b")")),
         map(nil, |_| Vec::new()),
@@ -136,7 +136,7 @@ pub fn env_reply_to(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
 }
 
 /// `env-to = "(" 1*address ")" / nil`
-pub fn env_to(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
+pub(crate) fn env_to(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
     alt((
         delimited(tag(b"("), many1(address), tag(b")")),
         map(nil, |_| Vec::new()),
@@ -144,7 +144,7 @@ pub fn env_to(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
 }
 
 /// `env-cc = "(" 1*address ")" / nil`
-pub fn env_cc(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
+pub(crate) fn env_cc(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
     alt((
         delimited(tag(b"("), many1(address), tag(b")")),
         map(nil, |_| Vec::new()),
@@ -152,7 +152,7 @@ pub fn env_cc(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
 }
 
 /// `env-bcc = "(" 1*address ")" / nil`
-pub fn env_bcc(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
+pub(crate) fn env_bcc(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
     alt((
         delimited(tag(b"("), many1(address), tag(b")")),
         map(nil, |_| Vec::new()),
@@ -161,13 +161,13 @@ pub fn env_bcc(input: &[u8]) -> IMAPResult<&[u8], Vec<Address>> {
 
 #[inline]
 /// `env-in-reply-to = nstring`
-pub fn env_in_reply_to(input: &[u8]) -> IMAPResult<&[u8], NString> {
+pub(crate) fn env_in_reply_to(input: &[u8]) -> IMAPResult<&[u8], NString> {
     nstring(input)
 }
 
 #[inline]
 /// `env-message-id = nstring`
-pub fn env_message_id(input: &[u8]) -> IMAPResult<&[u8], NString> {
+pub(crate) fn env_message_id(input: &[u8]) -> IMAPResult<&[u8], NString> {
     nstring(input)
 }
 
@@ -177,7 +177,7 @@ pub fn env_message_id(input: &[u8]) -> IMAPResult<&[u8], NString> {
 ///             addr-mailbox SP
 ///             addr-host
 ///             ")"`
-pub fn address(input: &[u8]) -> IMAPResult<&[u8], Address> {
+pub(crate) fn address(input: &[u8]) -> IMAPResult<&[u8], Address> {
     let mut parser = delimited(
         tag(b"("),
         tuple((addr_name, sp, addr_adl, sp, addr_mailbox, sp, addr_host)),
@@ -203,7 +203,7 @@ pub fn address(input: &[u8]) -> IMAPResult<&[u8], Address> {
 /// If non-NIL, holds phrase from [RFC-2822]
 /// mailbox after removing [RFC-2822] quoting
 /// TODO(misuse): use `Phrase`?
-pub fn addr_name(input: &[u8]) -> IMAPResult<&[u8], NString> {
+pub(crate) fn addr_name(input: &[u8]) -> IMAPResult<&[u8], NString> {
     nstring(input)
 }
 
@@ -212,7 +212,7 @@ pub fn addr_name(input: &[u8]) -> IMAPResult<&[u8], NString> {
 ///
 /// Holds route from [RFC-2822] route-addr if non-NIL
 /// TODO(misuse): use `Route`?
-pub fn addr_adl(input: &[u8]) -> IMAPResult<&[u8], NString> {
+pub(crate) fn addr_adl(input: &[u8]) -> IMAPResult<&[u8], NString> {
     nstring(input)
 }
 
@@ -223,7 +223,7 @@ pub fn addr_adl(input: &[u8]) -> IMAPResult<&[u8], NString> {
 /// if non-NIL and addr-host is NIL, holds [RFC-2822] group name.
 /// Otherwise, holds [RFC-2822] local-part after removing [RFC-2822] quoting
 /// TODO(misuse): use `GroupName` or `LocalPart`?
-pub fn addr_mailbox(input: &[u8]) -> IMAPResult<&[u8], NString> {
+pub(crate) fn addr_mailbox(input: &[u8]) -> IMAPResult<&[u8], NString> {
     nstring(input)
 }
 
@@ -233,7 +233,7 @@ pub fn addr_mailbox(input: &[u8]) -> IMAPResult<&[u8], NString> {
 /// NIL indicates [RFC-2822] group syntax.
 /// Otherwise, holds [RFC-2822] domain name
 /// TODO(misuse): use `DomainName`?
-pub fn addr_host(input: &[u8]) -> IMAPResult<&[u8], NString> {
+pub(crate) fn addr_host(input: &[u8]) -> IMAPResult<&[u8], NString> {
     nstring(input)
 }
 
diff --git a/src/extensions/compress.rs b/src/extensions/compress.rs
index 01d1edc3..ace01a77 100644
--- a/src/extensions/compress.rs
+++ b/src/extensions/compress.rs
@@ -22,12 +22,12 @@ use crate::{
 };
 
 /// `algorithm = "DEFLATE"`
-pub fn algorithm(input: &[u8]) -> IMAPResult<&[u8], CompressionAlgorithm> {
+pub(crate) fn algorithm(input: &[u8]) -> IMAPResult<&[u8], CompressionAlgorithm> {
     value(CompressionAlgorithm::Deflate, tag_no_case("DEFLATE"))(input)
 }
 
 /// `compress = "COMPRESS" SP algorithm`
-pub fn compress(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn compress(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     map(preceded(tag_no_case("COMPRESS "), algorithm), |algorithm| {
         CommandBody::Compress { algorithm }
     })(input)
diff --git a/src/extensions/enable.rs b/src/extensions/enable.rs
index e9e0c0e5..34a61eb5 100644
--- a/src/extensions/enable.rs
+++ b/src/extensions/enable.rs
@@ -36,7 +36,7 @@ use crate::{
 ///
 /// command-any =/ enable
 /// ```
-pub fn enable(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn enable(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((
         tag_no_case("ENABLE"),
         many1(preceded(sp, capability_enable)),
@@ -52,12 +52,12 @@ pub fn enable(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     ))
 }
 
-pub fn capability_enable(input: &[u8]) -> IMAPResult<&[u8], CapabilityEnable> {
+pub(crate) fn capability_enable(input: &[u8]) -> IMAPResult<&[u8], CapabilityEnable> {
     map(atom, CapabilityEnable::from)(input)
 }
 
 /// `enable-data = "ENABLED" *(SP capability)`
-pub fn enable_data(input: &[u8]) -> IMAPResult<&[u8], Data> {
+pub(crate) fn enable_data(input: &[u8]) -> IMAPResult<&[u8], Data> {
     let mut parser = tuple((
         tag_no_case(b"ENABLED"),
         many0(preceded(sp, capability_enable)),
diff --git a/src/extensions/idle.rs b/src/extensions/idle.rs
index aa9fe8e7..a7706561 100644
--- a/src/extensions/idle.rs
+++ b/src/extensions/idle.rs
@@ -33,7 +33,7 @@ use crate::{
 /// ```
 ///
 /// Valid only in Authenticated or Selected state
-pub fn idle(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn idle(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     value(CommandBody::Idle, tag_no_case("IDLE"))(input)
 }
 
@@ -51,7 +51,7 @@ pub fn idle(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 ///
 /// Note: This parser must be executed *instead* of the command parser
 /// when the server is in the IDLE state.
-pub fn idle_done(input: &[u8]) -> IMAPResult<&[u8], IdleDone> {
+pub(crate) fn idle_done(input: &[u8]) -> IMAPResult<&[u8], IdleDone> {
     value(IdleDone, tuple((tag_no_case("DONE"), crlf)))(input)
 }
 
diff --git a/src/extensions/move.rs b/src/extensions/move.rs
index 009e2525..947d1004 100644
--- a/src/extensions/move.rs
+++ b/src/extensions/move.rs
@@ -10,7 +10,7 @@ use crate::{codec::IMAPResult, command::CommandBody, mailbox::mailbox, sequence:
 /// ```abnf
 /// move = "MOVE" SP sequence-set SP mailbox
 /// ```
-pub fn r#move(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn r#move(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((tag_no_case(b"MOVE"), sp, sequence_set, sp, mailbox));
 
     let (remaining, (_, _, sequence_set, _, mailbox)) = parser(input)?;
diff --git a/src/extensions/quota.rs b/src/extensions/quota.rs
index 7e242573..f84566a8 100644
--- a/src/extensions/quota.rs
+++ b/src/extensions/quota.rs
@@ -24,7 +24,7 @@ use crate::{
 /// quota-root-name = astring
 /// ```
 #[inline]
-pub fn quota_root_name(input: &[u8]) -> IMAPResult<&[u8], AString> {
+pub(crate) fn quota_root_name(input: &[u8]) -> IMAPResult<&[u8], AString> {
     astring(input)
 }
 
@@ -32,7 +32,7 @@ pub fn quota_root_name(input: &[u8]) -> IMAPResult<&[u8], AString> {
 /// getquota = "GETQUOTA" SP quota-root-name
 /// ```
 #[inline]
-pub fn getquota(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn getquota(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((tag_no_case("GETQUOTA "), quota_root_name));
 
     let (remaining, (_, root)) = parser(input)?;
@@ -43,7 +43,7 @@ pub fn getquota(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 /// ```abnf
 /// getquotaroot = "GETQUOTAROOT" SP mailbox
 /// ```
-pub fn getquotaroot(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn getquotaroot(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((tag_no_case("GETQUOTAROOT "), mailbox));
 
     let (remaining, (_, mailbox)) = parser(input)?;
@@ -60,7 +60,7 @@ pub fn getquotaroot(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 ///
 /// resource-limit = number64
 /// ```
-pub fn quota_resource(input: &[u8]) -> IMAPResult<&[u8], QuotaGet> {
+pub(crate) fn quota_resource(input: &[u8]) -> IMAPResult<&[u8], QuotaGet> {
     let mut parser = tuple((resource_name, sp, number64, sp, number64));
 
     let (remaining, (resource, _, usage, _, limit)) = parser(input)?;
@@ -84,7 +84,7 @@ pub fn quota_resource(input: &[u8]) -> IMAPResult<&[u8], QuotaGet> {
 ///
 /// resource-name-ext = atom
 /// ```
-pub fn resource_name(input: &[u8]) -> IMAPResult<&[u8], Resource> {
+pub(crate) fn resource_name(input: &[u8]) -> IMAPResult<&[u8], Resource> {
     map(atom, Resource::from)(input)
 }
 
@@ -93,7 +93,7 @@ pub fn resource_name(input: &[u8]) -> IMAPResult<&[u8], Resource> {
 ///
 /// quota-list = "(" quota-resource *(SP quota-resource) ")"
 /// ```
-pub fn quota_response(input: &[u8]) -> IMAPResult<&[u8], Data> {
+pub(crate) fn quota_response(input: &[u8]) -> IMAPResult<&[u8], Data> {
     let mut parser = tuple((
         tag_no_case("QUOTA "),
         quota_root_name,
@@ -116,7 +116,7 @@ pub fn quota_response(input: &[u8]) -> IMAPResult<&[u8], Data> {
 /// ```abnf
 /// quotaroot-response = "QUOTAROOT" SP mailbox *(SP quota-root-name)
 /// ```
-pub fn quotaroot_response(input: &[u8]) -> IMAPResult<&[u8], Data> {
+pub(crate) fn quotaroot_response(input: &[u8]) -> IMAPResult<&[u8], Data> {
     let mut parser = tuple((
         tag_no_case("QUOTAROOT "),
         mailbox,
@@ -133,7 +133,7 @@ pub fn quotaroot_response(input: &[u8]) -> IMAPResult<&[u8], Data> {
 ///
 /// setquota-list = "(" [setquota-resource *(SP setquota-resource)] ")"
 /// ```
-pub fn setquota(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn setquota(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((
         tag_no_case("SETQUOTA "),
         quota_root_name,
@@ -149,7 +149,7 @@ pub fn setquota(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 /// ```abnf
 /// setquota-resource = resource-name SP resource-limit
 /// ```
-pub fn setquota_resource(input: &[u8]) -> IMAPResult<&[u8], QuotaSet> {
+pub(crate) fn setquota_resource(input: &[u8]) -> IMAPResult<&[u8], QuotaSet> {
     let mut parser = tuple((resource_name, sp, number64));
 
     let (remaining, (resource, _, limit)) = parser(input)?;
@@ -169,7 +169,7 @@ pub fn setquota_resource(input: &[u8]) -> IMAPResult<&[u8], QuotaSet> {
 // /// ```abnf
 // /// capability-quota = "QUOTASET" / capa-quota-res / "QUOTA"
 // /// ```
-// pub fn capability_quota(input: &[u8]) -> IMAPResult<&[u8], Capability> {
+// pub(crate) fn capability_quota(input: &[u8]) -> IMAPResult<&[u8], Capability> {
 //     alt((
 //         value(Capability::QuotaSet, tag_no_case("QUOTASET")),
 //         capa_quota_res,
@@ -180,7 +180,7 @@ pub fn setquota_resource(input: &[u8]) -> IMAPResult<&[u8], QuotaSet> {
 // /// ```abnf
 // /// capa-quota-res = "QUOTA=RES-" resource-name
 // /// ```
-// pub fn capa_quota_res(input: &[u8]) -> IMAPResult<&[u8], Capability> {
+// pub(crate) fn capa_quota_res(input: &[u8]) -> IMAPResult<&[u8], Capability> {
 //     let mut parser = preceded(tag_no_case("QUOTA=RES-"), resource_name);
 //
 //     let (remaining, resource) = parser(input)?;
diff --git a/src/fetch.rs b/src/fetch.rs
index 29881d21..f0b33f01 100644
--- a/src/fetch.rs
+++ b/src/fetch.rs
@@ -31,7 +31,7 @@ use crate::{
 ///              "UID" /
 ///              "BODY" section ["<" number "." nz-number ">"] /
 ///              "BODY.PEEK" section ["<" number "." nz-number ">"]`
-pub fn fetch_att(input: &[u8]) -> IMAPResult<&[u8], MessageDataItemName> {
+pub(crate) fn fetch_att(input: &[u8]) -> IMAPResult<&[u8], MessageDataItemName> {
     alt((
         value(MessageDataItemName::Envelope, tag_no_case(b"ENVELOPE")),
         value(MessageDataItemName::Flags, tag_no_case(b"FLAGS")),
@@ -90,7 +90,7 @@ pub fn fetch_att(input: &[u8]) -> IMAPResult<&[u8], MessageDataItemName> {
 /// `msg-att = "("
 ///            (msg-att-dynamic / msg-att-static) *(SP (msg-att-dynamic / msg-att-static))
 ///            ")"`
-pub fn msg_att(input: &[u8]) -> IMAPResult<&[u8], NonEmptyVec<MessageDataItem>> {
+pub(crate) fn msg_att(input: &[u8]) -> IMAPResult<&[u8], NonEmptyVec<MessageDataItem>> {
     delimited(
         tag(b"("),
         map(
@@ -104,7 +104,7 @@ pub fn msg_att(input: &[u8]) -> IMAPResult<&[u8], NonEmptyVec<MessageDataItem>>
 /// `msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")"`
 ///
 /// Note: MAY change for a message
-pub fn msg_att_dynamic(input: &[u8]) -> IMAPResult<&[u8], MessageDataItem> {
+pub(crate) fn msg_att_dynamic(input: &[u8]) -> IMAPResult<&[u8], MessageDataItem> {
     let mut parser = tuple((
         tag_no_case(b"FLAGS"),
         sp,
@@ -125,7 +125,7 @@ pub fn msg_att_dynamic(input: &[u8]) -> IMAPResult<&[u8], MessageDataItem> {
 ///                   "UID" SP uniqueid`
 ///
 /// Note: MUST NOT change for a message
-pub fn msg_att_static(input: &[u8]) -> IMAPResult<&[u8], MessageDataItem> {
+pub(crate) fn msg_att_static(input: &[u8]) -> IMAPResult<&[u8], MessageDataItem> {
     alt((
         map(
             tuple((tag_no_case(b"ENVELOPE"), sp, envelope)),
@@ -183,7 +183,7 @@ pub fn msg_att_static(input: &[u8]) -> IMAPResult<&[u8], MessageDataItem> {
 /// `uniqueid = nz-number`
 ///
 /// Note: Strictly ascending
-pub fn uniqueid(input: &[u8]) -> IMAPResult<&[u8], NonZeroU32> {
+pub(crate) fn uniqueid(input: &[u8]) -> IMAPResult<&[u8], NonZeroU32> {
     nz_number(input)
 }
 
diff --git a/src/flag.rs b/src/flag.rs
index 5feb52e4..d00bcb5c 100644
--- a/src/flag.rs
+++ b/src/flag.rs
@@ -25,7 +25,7 @@ use crate::{codec::IMAPResult, core::atom};
 /// ```
 ///
 /// Note: Does not include "\Recent"
-pub fn flag(input: &[u8]) -> IMAPResult<&[u8], Flag> {
+pub(crate) fn flag(input: &[u8]) -> IMAPResult<&[u8], Flag> {
     alt((
         map(preceded(char('\\'), atom), Flag::system_or_extension),
         map(atom, Flag::Keyword),
@@ -35,7 +35,7 @@ pub fn flag(input: &[u8]) -> IMAPResult<&[u8], Flag> {
 // Note(duesee): This was inlined into [`flag`].
 // #[inline]
 // /// `flag-keyword = atom`
-// pub fn flag_keyword(input: &[u8]) -> IMAPResult<&[u8], Flag> {
+// pub(crate) fn flag_keyword(input: &[u8]) -> IMAPResult<&[u8], Flag> {
 //     map(atom, Flag::Keyword)(input)
 // }
 
@@ -49,17 +49,17 @@ pub fn flag(input: &[u8]) -> IMAPResult<&[u8], Flag> {
 // /// Client implementations MUST accept flag-extension flags.
 // /// Server implementations MUST NOT generate flag-extension flags
 // /// except as defined by future standard or standards-track revisions of this specification.
-// pub fn flag_extension(input: &[u8]) -> IMAPResult<&[u8], Atom> {
+// pub(crate) fn flag_extension(input: &[u8]) -> IMAPResult<&[u8], Atom> {
 //     preceded(tag(b"\\"), atom)(input)
 // }
 
 /// `flag-list = "(" [flag *(SP flag)] ")"`
-pub fn flag_list(input: &[u8]) -> IMAPResult<&[u8], Vec<Flag>> {
+pub(crate) fn flag_list(input: &[u8]) -> IMAPResult<&[u8], Vec<Flag>> {
     delimited(tag(b"("), separated_list0(sp, flag), tag(b")"))(input)
 }
 
 /// `flag-fetch = flag / "\Recent"`
-pub fn flag_fetch(input: &[u8]) -> IMAPResult<&[u8], FlagFetch> {
+pub(crate) fn flag_fetch(input: &[u8]) -> IMAPResult<&[u8], FlagFetch> {
     if let Ok((rem, peek)) = recognize(tuple((char('\\'), atom)))(input) {
         if peek.to_ascii_lowercase() == b"\\recent" {
             return Ok((rem, FlagFetch::Recent));
@@ -70,7 +70,7 @@ pub fn flag_fetch(input: &[u8]) -> IMAPResult<&[u8], FlagFetch> {
 }
 
 /// `flag-perm = flag / "\*"`
-pub fn flag_perm(input: &[u8]) -> IMAPResult<&[u8], FlagPerm> {
+pub(crate) fn flag_perm(input: &[u8]) -> IMAPResult<&[u8], FlagPerm> {
     alt((
         value(FlagPerm::AllowNewKeywords, tag("\\*")),
         map(flag, FlagPerm::Flag),
@@ -84,7 +84,7 @@ pub fn flag_perm(input: &[u8]) -> IMAPResult<&[u8], FlagPerm> {
 ///
 /// TODO(#155): ABNF enforces that sflag is not used more than once.
 ///             We could parse any flag and check for multiple occurrences of sflag later.
-pub fn mbx_list_flags(input: &[u8]) -> IMAPResult<&[u8], Vec<FlagNameAttribute>> {
+pub(crate) fn mbx_list_flags(input: &[u8]) -> IMAPResult<&[u8], Vec<FlagNameAttribute>> {
     let (remaining, flags) =
         separated_list1(sp, map(preceded(char('\\'), atom), FlagNameAttribute::from))(input)?;
 
@@ -110,7 +110,7 @@ pub fn mbx_list_flags(input: &[u8]) -> IMAPResult<&[u8], Vec<FlagNameAttribute>>
 // /// ```
 // ///
 // /// Other flags; multiple possible per LIST response
-// pub fn mbx_list_oflag(input: &[u8]) -> IMAPResult<&[u8], FlagNameAttribute> {
+// pub(crate) fn mbx_list_oflag(input: &[u8]) -> IMAPResult<&[u8], FlagNameAttribute> {
 //     alt((
 //         value(
 //             FlagNameAttribute::Noinferiors,
@@ -126,7 +126,7 @@ pub fn mbx_list_flags(input: &[u8]) -> IMAPResult<&[u8], Vec<FlagNameAttribute>>
 // /// ```
 // ///
 // /// Selectability flags; only one per LIST response
-// pub fn mbx_list_sflag(input: &[u8]) -> IMAPResult<&[u8], FlagNameAttribute> {
+// pub(crate) fn mbx_list_sflag(input: &[u8]) -> IMAPResult<&[u8], FlagNameAttribute> {
 //     alt((
 //         value(FlagNameAttribute::Noselect, tag_no_case(b"\\Noselect")),
 //         value(FlagNameAttribute::Marked, tag_no_case(b"\\Marked")),
diff --git a/src/mailbox.rs b/src/mailbox.rs
index fa7351fd..968f9812 100644
--- a/src/mailbox.rs
+++ b/src/mailbox.rs
@@ -26,7 +26,7 @@ use crate::{
 };
 
 /// `list-mailbox = 1*list-char / string`
-pub fn list_mailbox(input: &[u8]) -> IMAPResult<&[u8], ListMailbox> {
+pub(crate) fn list_mailbox(input: &[u8]) -> IMAPResult<&[u8], ListMailbox> {
     alt((
         map(take_while1(is_list_char), |bytes: &[u8]| {
             // # Safety
@@ -43,7 +43,7 @@ pub fn list_mailbox(input: &[u8]) -> IMAPResult<&[u8], ListMailbox> {
 }
 
 /// `list-char = ATOM-CHAR / list-wildcards / resp-specials`
-pub fn is_list_char(i: u8) -> bool {
+pub(crate) fn is_list_char(i: u8) -> bool {
     is_atom_char(i) || is_list_wildcards(i) || is_resp_specials(i)
 }
 
@@ -56,7 +56,7 @@ pub fn is_list_char(i: u8) -> bool {
 /// "I" "N" "B" "O" "X" is considered to be INBOX and not an astring.
 ///
 /// Refer to section 5.1 for further semantic details of mailbox names.
-pub fn mailbox(input: &[u8]) -> IMAPResult<&[u8], Mailbox> {
+pub(crate) fn mailbox(input: &[u8]) -> IMAPResult<&[u8], Mailbox> {
     map(astring, Mailbox::from)(input)
 }
 
@@ -67,7 +67,7 @@ pub fn mailbox(input: &[u8]) -> IMAPResult<&[u8], Mailbox> {
 ///                 "STATUS" SP mailbox SP "(" [status-att-list] ")" /
 ///                 number SP "EXISTS" /
 ///                 number SP "RECENT"`
-pub fn mailbox_data(input: &[u8]) -> IMAPResult<&[u8], Data> {
+pub(crate) fn mailbox_data(input: &[u8]) -> IMAPResult<&[u8], Data> {
     alt((
         map(
             tuple((tag_no_case(b"FLAGS"), sp, flag_list)),
@@ -125,7 +125,7 @@ pub fn mailbox_data(input: &[u8]) -> IMAPResult<&[u8], Data> {
 ///                 (DQUOTE QUOTED-CHAR DQUOTE / nil) SP
 ///                 mailbox`
 #[allow(clippy::type_complexity)]
-pub fn mailbox_list(
+pub(crate) fn mailbox_list(
     input: &[u8],
 ) -> IMAPResult<&[u8], (Option<Vec<FlagNameAttribute>>, Option<QuotedChar>, Mailbox)> {
     let mut parser = tuple((
diff --git a/src/response.rs b/src/response.rs
index cec3cf54..bd4d6c6e 100644
--- a/src/response.rs
+++ b/src/response.rs
@@ -31,7 +31,7 @@ use crate::{
 // ----- greeting -----
 
 /// `greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF`
-pub fn greeting(input: &[u8]) -> IMAPResult<&[u8], Greeting> {
+pub(crate) fn greeting(input: &[u8]) -> IMAPResult<&[u8], Greeting> {
     let mut parser = tuple((
         tag(b"*"),
         sp,
@@ -51,7 +51,9 @@ pub fn greeting(input: &[u8]) -> IMAPResult<&[u8], Greeting> {
 ///
 /// Authentication condition
 #[allow(clippy::type_complexity)]
-pub fn resp_cond_auth(input: &[u8]) -> IMAPResult<&[u8], (GreetingKind, (Option<Code>, Text))> {
+pub(crate) fn resp_cond_auth(
+    input: &[u8],
+) -> IMAPResult<&[u8], (GreetingKind, (Option<Code>, Text))> {
     let mut parser = tuple((
         alt((
             value(GreetingKind::Ok, tag_no_case(b"OK")),
@@ -67,7 +69,7 @@ pub fn resp_cond_auth(input: &[u8]) -> IMAPResult<&[u8], (GreetingKind, (Option<
 }
 
 /// `resp-text = ["[" resp-text-code "]" SP] text`
-pub fn resp_text(input: &[u8]) -> IMAPResult<&[u8], (Option<Code>, Text)> {
+pub(crate) fn resp_text(input: &[u8]) -> IMAPResult<&[u8], (Option<Code>, Text)> {
     tuple((
         opt(terminated(
             preceded(
@@ -101,7 +103,7 @@ pub fn resp_text(input: &[u8]) -> IMAPResult<&[u8], (Option<Code>, Text)> {
 ///                   atom [SP 1*<any TEXT-CHAR except "]">]`
 ///
 /// Note: See errata id: 261
-pub fn resp_text_code(input: &[u8]) -> IMAPResult<&[u8], Code> {
+pub(crate) fn resp_text_code(input: &[u8]) -> IMAPResult<&[u8], Code> {
     alt((
         value(Code::Alert, tag_no_case(b"ALERT")),
         map(
@@ -160,7 +162,7 @@ pub fn resp_text_code(input: &[u8]) -> IMAPResult<&[u8], Code> {
 ///
 /// Servers MUST implement the STARTTLS, AUTH=PLAIN, and LOGINDISABLED capabilities
 /// Servers which offer RFC 1730 compatibility MUST list "IMAP4" as the first capability.
-pub fn capability_data(input: &[u8]) -> IMAPResult<&[u8], NonEmptyVec<Capability>> {
+pub(crate) fn capability_data(input: &[u8]) -> IMAPResult<&[u8], NonEmptyVec<Capability>> {
     let mut parser = tuple((
         tag_no_case("CAPABILITY"),
         sp,
@@ -175,12 +177,12 @@ pub fn capability_data(input: &[u8]) -> IMAPResult<&[u8], NonEmptyVec<Capability
 /// `capability = ("AUTH=" auth-type) /
 ///               "COMPRESS=" algorithm / ; RFC 4978
 ///               atom`
-pub fn capability(input: &[u8]) -> IMAPResult<&[u8], Capability> {
+pub(crate) fn capability(input: &[u8]) -> IMAPResult<&[u8], Capability> {
     map(atom, Capability::from)(input)
 }
 
 /// `resp-cond-bye = "BYE" SP resp-text`
-pub fn resp_cond_bye(input: &[u8]) -> IMAPResult<&[u8], (Option<Code>, Text)> {
+pub(crate) fn resp_cond_bye(input: &[u8]) -> IMAPResult<&[u8], (Option<Code>, Text)> {
     let mut parser = tuple((tag_no_case(b"BYE"), sp, resp_text));
 
     let (remaining, (_, _, resp_text)) = parser(input)?;
@@ -191,7 +193,7 @@ pub fn resp_cond_bye(input: &[u8]) -> IMAPResult<&[u8], (Option<Code>, Text)> {
 // ----- response -----
 
 /// `response = *(continue-req / response-data) response-done`
-pub fn response(input: &[u8]) -> IMAPResult<&[u8], Response> {
+pub(crate) fn response(input: &[u8]) -> IMAPResult<&[u8], Response> {
     // Divert from standard here for better usability.
     // response_data already contains the bye response, thus
     // response_done could also be response_tagged.
@@ -205,7 +207,7 @@ pub fn response(input: &[u8]) -> IMAPResult<&[u8], Response> {
 }
 
 /// `continue-req = "+" SP (resp-text / base64) CRLF`
-pub fn continue_req(input: &[u8]) -> IMAPResult<&[u8], Continue> {
+pub(crate) fn continue_req(input: &[u8]) -> IMAPResult<&[u8], Continue> {
     // We can't map the output of `resp_text` directly to `Continue::basic()` because we might end
     // up with a subset of `Text` that is valid base64 and will panic on `unwrap()`. Thus, we first
     // let the parsing finish and only later map to `Continue`.
@@ -257,7 +259,7 @@ pub fn continue_req(input: &[u8]) -> IMAPResult<&[u8], Continue> {
 ///                    message-data /
 ///                    capability-data
 ///                  ) CRLF`
-pub fn response_data(input: &[u8]) -> IMAPResult<&[u8], Response> {
+pub(crate) fn response_data(input: &[u8]) -> IMAPResult<&[u8], Response> {
     let mut parser = tuple((
         tag(b"*"),
         sp,
@@ -306,7 +308,7 @@ pub fn response_data(input: &[u8]) -> IMAPResult<&[u8], Response> {
 /// `resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text`
 ///
 /// Status condition
-pub fn resp_cond_state(input: &[u8]) -> IMAPResult<&[u8], (&str, Option<Code>, Text)> {
+pub(crate) fn resp_cond_state(input: &[u8]) -> IMAPResult<&[u8], (&str, Option<Code>, Text)> {
     let mut parser = tuple((
         alt((tag_no_case("OK"), tag_no_case("NO"), tag_no_case("BAD"))),
         sp,
@@ -325,12 +327,12 @@ pub fn resp_cond_state(input: &[u8]) -> IMAPResult<&[u8], (&str, Option<Code>, T
 }
 
 /// `response-done = response-tagged / response-fatal`
-pub fn response_done(input: &[u8]) -> IMAPResult<&[u8], Status> {
+pub(crate) fn response_done(input: &[u8]) -> IMAPResult<&[u8], Status> {
     alt((response_tagged, response_fatal))(input)
 }
 
 /// `response-tagged = tag SP resp-cond-state CRLF`
-pub fn response_tagged(input: &[u8]) -> IMAPResult<&[u8], Status> {
+pub(crate) fn response_tagged(input: &[u8]) -> IMAPResult<&[u8], Status> {
     let mut parser = tuple((tag_imap, sp, resp_cond_state, crlf));
 
     let (remaining, (tag, _, (raw_status, code, text), _)) = parser(input)?;
@@ -360,7 +362,7 @@ pub fn response_tagged(input: &[u8]) -> IMAPResult<&[u8], Status> {
 /// `response-fatal = "*" SP resp-cond-bye CRLF`
 ///
 /// Server closes connection immediately
-pub fn response_fatal(input: &[u8]) -> IMAPResult<&[u8], Status> {
+pub(crate) fn response_fatal(input: &[u8]) -> IMAPResult<&[u8], Status> {
     let mut parser = tuple((tag(b"*"), sp, resp_cond_bye, crlf));
 
     let (remaining, (_, _, (code, text), _)) = parser(input)?;
@@ -369,7 +371,7 @@ pub fn response_fatal(input: &[u8]) -> IMAPResult<&[u8], Status> {
 }
 
 /// `message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att))`
-pub fn message_data(input: &[u8]) -> IMAPResult<&[u8], Data> {
+pub(crate) fn message_data(input: &[u8]) -> IMAPResult<&[u8], Data> {
     let (remaining, seq) = terminated(nz_number, sp)(input)?;
 
     alt((
diff --git a/src/search.rs b/src/search.rs
index 4ae94f96..4901f0ea 100644
--- a/src/search.rs
+++ b/src/search.rs
@@ -2,7 +2,7 @@
 
 use abnf_core::streaming::sp;
 /// Re-export everything from imap-types.
-pub use imap_types::search::*;
+pub(crate) use imap_types::search::*;
 use nom::{
     branch::alt,
     bytes::{complete::tag, streaming::tag_no_case},
@@ -25,7 +25,7 @@ use crate::{
 /// Note: CHARSET argument MUST be registered with IANA
 ///
 /// errata id: 261
-pub fn search(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
+pub(crate) fn search(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
     let mut parser = tuple((
         tag_no_case(b"SEARCH"),
         opt(map(
@@ -94,7 +94,9 @@ pub fn search(input: &[u8]) -> IMAPResult<&[u8], CommandBody> {
 ///
 /// This parser is recursively defined. Thus, in order to not overflow the stack,
 /// it is needed to limit how may recursions are allowed. (8 should suffice).
-pub fn search_key(remaining_recursions: usize) -> impl Fn(&[u8]) -> IMAPResult<&[u8], SearchKey> {
+pub(crate) fn search_key(
+    remaining_recursions: usize,
+) -> impl Fn(&[u8]) -> IMAPResult<&[u8], SearchKey> {
     move |input: &[u8]| search_key_limited(input, remaining_recursions)
 }
 
diff --git a/src/section.rs b/src/section.rs
index 0dc0f91c..3169430d 100644
--- a/src/section.rs
+++ b/src/section.rs
@@ -19,12 +19,12 @@ use crate::{
 };
 
 /// `section = "[" [section-spec] "]"`
-pub fn section(input: &[u8]) -> IMAPResult<&[u8], Option<Section>> {
+pub(crate) fn section(input: &[u8]) -> IMAPResult<&[u8], Option<Section>> {
     delimited(tag(b"["), opt(section_spec), tag(b"]"))(input)
 }
 
 /// `section-spec = section-msgtext / (section-part ["." section-text])`
-pub fn section_spec(input: &[u8]) -> IMAPResult<&[u8], Section> {
+pub(crate) fn section_spec(input: &[u8]) -> IMAPResult<&[u8], Section> {
     alt((
         map(section_msgtext, |part_specifier| match part_specifier {
             PartSpecifier::PartNumber(_) => unreachable!(),
@@ -61,7 +61,7 @@ pub fn section_spec(input: &[u8]) -> IMAPResult<&[u8], Section> {
 /// `section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / "TEXT"`
 ///
 /// Top-level or MESSAGE/RFC822 part
-pub fn section_msgtext(input: &[u8]) -> IMAPResult<&[u8], PartSpecifier> {
+pub(crate) fn section_msgtext(input: &[u8]) -> IMAPResult<&[u8], PartSpecifier> {
     alt((
         map(
             tuple((tag_no_case(b"HEADER.FIELDS.NOT"), sp, header_list)),
@@ -80,7 +80,7 @@ pub fn section_msgtext(input: &[u8]) -> IMAPResult<&[u8], PartSpecifier> {
 /// `section-part = nz-number *("." nz-number)`
 ///
 /// Body part nesting
-pub fn section_part(input: &[u8]) -> IMAPResult<&[u8], NonEmptyVec<NonZeroU32>> {
+pub(crate) fn section_part(input: &[u8]) -> IMAPResult<&[u8], NonEmptyVec<NonZeroU32>> {
     map(
         separated_list1(tag(b"."), nz_number),
         NonEmptyVec::unvalidated,
@@ -90,7 +90,7 @@ pub fn section_part(input: &[u8]) -> IMAPResult<&[u8], NonEmptyVec<NonZeroU32>>
 /// `section-text = section-msgtext / "MIME"`
 ///
 /// Text other than actual body part (headers, etc.)
-pub fn section_text(input: &[u8]) -> IMAPResult<&[u8], PartSpecifier> {
+pub(crate) fn section_text(input: &[u8]) -> IMAPResult<&[u8], PartSpecifier> {
     alt((
         section_msgtext,
         value(PartSpecifier::Mime, tag_no_case(b"MIME")),
@@ -98,7 +98,7 @@ pub fn section_text(input: &[u8]) -> IMAPResult<&[u8], PartSpecifier> {
 }
 
 /// `header-list = "(" header-fld-name *(SP header-fld-name) ")"`
-pub fn header_list(input: &[u8]) -> IMAPResult<&[u8], NonEmptyVec<AString>> {
+pub(crate) fn header_list(input: &[u8]) -> IMAPResult<&[u8], NonEmptyVec<AString>> {
     map(
         delimited(tag(b"("), separated_list1(sp, header_fld_name), tag(b")")),
         NonEmptyVec::unvalidated,
@@ -107,7 +107,7 @@ pub fn header_list(input: &[u8]) -> IMAPResult<&[u8], NonEmptyVec<AString>> {
 
 #[inline]
 /// `header-fld-name = astring`
-pub fn header_fld_name(input: &[u8]) -> IMAPResult<&[u8], AString> {
+pub(crate) fn header_fld_name(input: &[u8]) -> IMAPResult<&[u8], AString> {
     astring(input)
 }
 
diff --git a/src/sequence.rs b/src/sequence.rs
index da21dc08..800a1ede 100644
--- a/src/sequence.rs
+++ b/src/sequence.rs
@@ -34,7 +34,7 @@ use crate::{
 /// Simplified:
 ///
 /// `sequence-set = (seq-number / seq-range) *("," (seq-number / seq-range))`
-pub fn sequence_set(input: &[u8]) -> IMAPResult<&[u8], SequenceSet> {
+pub(crate) fn sequence_set(input: &[u8]) -> IMAPResult<&[u8], SequenceSet> {
     map(
         separated_list1(
             tag(b","),
@@ -56,7 +56,7 @@ pub fn sequence_set(input: &[u8]) -> IMAPResult<&[u8], SequenceSet> {
 ///
 /// Example: a unique identifier sequence range of 3291:* includes the UID
 ///          of the last message in the mailbox, even if that value is less than 3291.
-pub fn seq_range(input: &[u8]) -> IMAPResult<&[u8], (SeqOrUid, SeqOrUid)> {
+pub(crate) fn seq_range(input: &[u8]) -> IMAPResult<&[u8], (SeqOrUid, SeqOrUid)> {
     let mut parser = tuple((seq_number, tag(b":"), seq_number));
 
     let (remaining, (from, _, to)) = parser(input)?;
@@ -77,7 +77,7 @@ pub fn seq_range(input: &[u8]) -> IMAPResult<&[u8], (SeqOrUid, SeqOrUid)> {
 /// The server should respond with a tagged BAD response to a command that uses a message
 /// sequence number greater than the number of messages in the selected mailbox.
 /// This includes "*" if the selected mailbox is empty.
-pub fn seq_number(input: &[u8]) -> IMAPResult<&[u8], SeqOrUid> {
+pub(crate) fn seq_number(input: &[u8]) -> IMAPResult<&[u8], SeqOrUid> {
     alt((
         map(nz_number, SeqOrUid::Value),
         value(SeqOrUid::Asterisk, tag(b"*")),
diff --git a/src/status.rs b/src/status.rs
index 5c0a661a..cebcf889 100644
--- a/src/status.rs
+++ b/src/status.rs
@@ -23,7 +23,7 @@ use crate::{
 ///               "UIDNEXT" /
 ///               "UIDVALIDITY" /
 ///               "UNSEEN"`
-pub fn status_att(input: &[u8]) -> IMAPResult<&[u8], StatusDataItemName> {
+pub(crate) fn status_att(input: &[u8]) -> IMAPResult<&[u8], StatusDataItemName> {
     alt((
         value(StatusDataItemName::Messages, tag_no_case(b"MESSAGES")),
         value(StatusDataItemName::Recent, tag_no_case(b"RECENT")),
@@ -48,7 +48,7 @@ pub fn status_att(input: &[u8]) -> IMAPResult<&[u8], StatusDataItemName> {
 /// `status-att-list = status-att-val *(SP status-att-val)`
 ///
 /// Note: See errata id: 261
-pub fn status_att_list(input: &[u8]) -> IMAPResult<&[u8], Vec<StatusDataItem>> {
+pub(crate) fn status_att_list(input: &[u8]) -> IMAPResult<&[u8], Vec<StatusDataItem>> {
     separated_list1(sp, status_att_val)(input)
 }
 


Test patch:
diff --git a/src/testing.rs b/src/testing.rs
index 3f458af0..a1c7ca72 100644
--- a/src/testing.rs
+++ b/src/testing.rs
@@ -7,7 +7,9 @@ use crate::{
     utils::escape_byte_string,
 };
 
-pub fn known_answer_test_encode((test_object, expected_bytes): (impl Encode, impl AsRef<[u8]>)) {
+pub(crate) fn known_answer_test_encode(
+    (test_object, expected_bytes): (impl Encode, impl AsRef<[u8]>),
+) {
     let expected_bytes = expected_bytes.as_ref();
     let got_bytes = test_object.encode().dump();
     let got_bytes = got_bytes.as_slice();
@@ -24,7 +26,7 @@ pub fn known_answer_test_encode((test_object, expected_bytes): (impl Encode, imp
     }
 }
 
-pub fn known_answer_test_parse<'a, O, P>(
+pub(crate) fn known_answer_test_parse<'a, O, P>(
     (test, expected_remainder, expected_object): (&'a [u8], &[u8], O),
     parser: P,
 ) where
@@ -40,7 +42,7 @@ pub fn known_answer_test_parse<'a, O, P>(
 // we tried it and failed to provide a cleaner solution. Thus, it's a macro for now.
 macro_rules! impl_kat_inverse {
     ($fn_name:ident, $object:ty) => {
-        pub fn $fn_name(tests: &[(&[u8], &[u8], $object)]) {
+        pub(crate) fn $fn_name(tests: &[(&[u8], &[u8], $object)]) {
             for (no, (test_input, expected_remainder, expected_object)) in tests.iter().enumerate()
             {
                 println!("# {no}");