// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
/*
 *  Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *  SPDX-License-Identifier: Apache-2.0
 */

use crate::endpoint_lib::diagnostic::DiagnosticCollector;

pub(crate) fn is_valid_host_label(label: &str, allow_dots: bool, e: &mut DiagnosticCollector) -> bool {
    let bytes = label.as_bytes();
    if allow_dots {
        let mut start = 0;
        for i in 0..bytes.len() {
            if bytes[i] == b'.' {
                if !is_valid_segment(bytes, start, i, e) {
                    return false;
                }
                start = i + 1;
            }
        }
        is_valid_segment(bytes, start, bytes.len(), e)
    } else {
        is_valid_segment(bytes, 0, bytes.len(), e)
    }
}

#[inline]
fn is_valid_segment(bytes: &[u8], start: usize, end: usize, e: &mut DiagnosticCollector) -> bool {
    let len = end - start;
    if len == 0 || len > 63 {
        e.report_error("host was too short or too long");
        return false;
    }
    if bytes[start] == b'-' {
        e.report_error("cannot start with `-`");
        return false;
    }
    for &b in &bytes[start..end] {
        if !b.is_ascii_alphanumeric() && b != b'-' {
            return false;
        }
    }
    true
}

#[cfg(all(test, feature = "gated-tests"))]
mod test {
    use proptest::proptest;

    fn is_valid_host_label(label: &str, allow_dots: bool) -> bool {
        super::is_valid_host_label(label, allow_dots, &mut DiagnosticCollector::new())
    }

    #[allow(clippy::bool_assert_comparison)]
    #[test]
    fn basic_cases() {
        assert_eq!(is_valid_host_label("", false), false);
        assert_eq!(is_valid_host_label("", true), false);
        assert_eq!(is_valid_host_label(".", true), false);
        assert_eq!(is_valid_host_label("a.b", true), true);
        assert_eq!(is_valid_host_label("a.b", false), false);
        assert_eq!(is_valid_host_label("a.b.", true), false);
        assert_eq!(is_valid_host_label("a.b.c", true), true);
        assert_eq!(is_valid_host_label("a_b", true), false);
        assert_eq!(is_valid_host_label(&"a".repeat(64), false), false);
        assert_eq!(is_valid_host_label(&format!("{}.{}", "a".repeat(63), "a".repeat(63)), true), true);
    }

    #[allow(clippy::bool_assert_comparison)]
    #[test]
    fn start_bounds() {
        assert_eq!(is_valid_host_label("-foo", false), false);
        assert_eq!(is_valid_host_label("-foo", true), false);
        assert_eq!(is_valid_host_label(".foo", true), false);
        assert_eq!(is_valid_host_label("a-b.foo", true), true);
    }

    #[allow(clippy::bool_assert_comparison)]
    #[test]
    fn non_ascii_rejected() {
        // DNS host labels only allow ASCII alphanumeric and hyphens (RFC 952/1123)
        assert_eq!(is_valid_host_label("café", false), false);
        assert_eq!(is_valid_host_label("bücher", false), false);
        assert_eq!(is_valid_host_label("日本語", false), false);
        assert_eq!(is_valid_host_label("a.café.b", true), false);
        assert_eq!(is_valid_host_label("🚀rocket", false), false);
        // ASCII is fine
        assert_eq!(is_valid_host_label("abc123", false), true);
        assert_eq!(is_valid_host_label("a-b-c", false), true);
    }

    use crate::endpoint_lib::diagnostic::DiagnosticCollector;
    use proptest::prelude::*;
    proptest! {
        #[test]
        fn no_panics(s in any::<String>(), dots in any::<bool>()) {
            is_valid_host_label(&s, dots);
        }
    }
}
