use crate::v4::error::Result;
use serde::{Deserialize, Serialize};

/// An option that represents a string of variable length with a minimum length of 1.
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct StringOption(String);

impl StringOption {
    /// Create a `StringOption`. Length must be greater than 0.
    pub fn new(value: String) -> Result<Self> {
        if value.is_empty() {
            return Err("Must have length of at least 1");
        }

        Ok(Self(value))
    }

    /// Used, when serializing, to add to the byte buffer.
    #[inline]
    pub fn extend_into(&self, bytes: &mut Vec<u8>, tag: u8) {
        bytes.push(tag); // tag
        bytes.push(self.0.len() as u8); // length
        bytes.extend_from_slice(self.0.as_bytes()); // value
    }
}

impl TryFrom<String> for StringOption {
    type Error = &'static str;

    fn try_from(value: String) -> std::result::Result<Self, Self::Error> {
        StringOption::new(value)
    }
}

impl From<&[u8]> for StringOption {
    fn from(value: &[u8]) -> Self {
        Self(String::from_utf8_lossy(value).to_string())
    }
}
