httpio 0.2.4

A transport-agnostic, async HTTP/1.1 client library for any runtime.
Documentation
use std::borrow::{Borrow, Cow};

use crate::utils::string_util;

#[derive(Debug)]
pub struct KeyValue<'a, T> {
    pub key: Cow<'a, str>,
    pub value: T,
}

impl<'a, T> KeyValue<'a, T> {
    pub fn new(key: Cow<'a, str>, value: T) -> KeyValue<'a, T> {
        KeyValue { key, value }
    }

    pub fn key(&self) -> &str {
        &self.key
    }

    pub fn value(&self) -> &T {
        self.value.borrow()
    }
}

impl<'a, T: Clone> Clone for KeyValue<'a, T> {
    fn clone(&self) -> Self {
        Self {
            key: self.key.clone(),
            value: self.value.clone(),
        }
    }
}

impl<'a, T: ToString> KeyValue<'a, T> {
    pub fn to_string_with_delimiter(&self, delimiter: &str) -> String {
        string_util::join_with_delimiter(&self.key, &self.value.to_string(), delimiter)
    }
}

impl<'a, T: ToString> ToString for KeyValue<'a, T> {
    fn to_string(&self) -> String {
        self.to_string_with_delimiter(":")
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::borrow::Cow;

    #[test]
    fn test_new() {
        let kv = KeyValue::new(Cow::Borrowed("key"), 42);
        assert_eq!(kv.key(), "key");
        assert_eq!(kv.value(), &42);
    }

    #[test]
    fn test_owned_key() {
        let kv = KeyValue::new(Cow::Owned("key".to_string()), "value");
        assert_eq!(kv.key(), "key");
        assert_eq!(kv.value(), &"value");
    }

    #[test]
    fn test_borrowed_key() {
        let key = "test_key";
        let kv = KeyValue::new(Cow::Borrowed(key), 123);
        assert_eq!(kv.key(), "test_key");
        assert_eq!(kv.value(), &123);
    }

    #[test]
    fn test_to_string_with_delimiter() {
        let kv = KeyValue::new(Cow::Borrowed("name"), "John");
        assert_eq!(kv.to_string_with_delimiter("="), "name=John");
        assert_eq!(kv.to_string_with_delimiter(" -> "), "name -> John");
    }

    #[test]
    fn test_to_string_default() {
        let kv = KeyValue::new(Cow::Borrowed("id"), 456);
        assert_eq!(kv.to_string(), "id:456");
    }

    #[test]
    fn test_clone() {
        let kv1 = KeyValue::new(Cow::Borrowed("key"), "value");
        let kv2 = kv1.clone();

        assert_eq!(kv1.key(), kv2.key());
        assert_eq!(kv1.value(), kv2.value());
    }

    #[test]
    fn test_complex_value() {
        #[derive(Clone, PartialEq, Debug)]
        struct Person {
            name: String,
            age: u32,
        }

        impl ToString for Person {
            fn to_string(&self) -> String {
                format!("{}:{}", self.name, self.age)
            }
        }

        let person = Person {
            name: "Alice".to_string(),
            age: 30,
        };

        let kv = KeyValue::new(Cow::Borrowed("person"), person.clone());
        assert_eq!(kv.key(), "person");
        assert_eq!(kv.value(), &person);
        assert_eq!(kv.to_string(), "person:Alice:30");
    }

    #[test]
    fn test_empty_key() {
        let kv = KeyValue::new(Cow::Borrowed(""), "value");
        assert_eq!(kv.key(), "");
        assert_eq!(kv.value(), &"value");
        assert_eq!(kv.to_string(), ":value");
    }

    #[test]
    fn test_numeric_value() {
        let kv = KeyValue::new(Cow::Borrowed("count"), 42.5);
        assert_eq!(kv.key(), "count");
        assert_eq!(kv.value(), &42.5);
        assert_eq!(kv.to_string(), "count:42.5");
    }
}