/*!
Contains an ffi-safe equivalent of `&'a str`.
*/

use std::{
    borrow::{Cow,Borrow},
    fmt::{self, Display},
    ops::{Deref, Index},
    str,
};

#[allow(unused_imports)]
use core_extensions::prelude::*;

use serde::{Deserialize, Deserializer, Serialize, Serializer};

use crate::std_types::{RSlice, RString};

/**
Ffi-safe equivalent of `&'a str`

# Example

This defines a function that returns the first word in a string.

```
use abi_stable::{
    std_types::RStr,
    sabi_extern_fn,
};


#[sabi_extern_fn]
fn first_word(phrase:RStr<'_>)->RStr<'_>{
    match phrase.as_str().split_whitespace().next() {
        Some(x)=>x.into(),
        None=>"".into()
    }
}

```

*/
#[repr(C)]
#[derive(Copy, Clone, StableAbi)]
pub struct RStr<'a> {
    inner: RSlice<'a, u8>,
}

impl<'a> RStr<'a> {
    /// An empty `RStr`.
    pub const EMPTY: Self = RStr {
        inner: RSlice::EMPTY,
    };
}

impl<'a> RStr<'a> {
    /// Constructs an empty `RStr<'a>`.
    ///
    /// # Example
    ///
    /// ```
    /// use abi_stable::std_types::RStr;
    ///
    /// const STR:RStr<'static>=RStr::empty();
    ///
    /// assert_eq!(STR,RStr::from(""));
    ///
    /// ```
    #[inline]
    pub const fn empty() -> Self {
        Self::EMPTY
    }

    /// Constructs an `RStr<'a>` from a pointer to the first byte,
    /// and a length.
    ///
    /// # Safety
    ///
    /// Callers must ensure that:
    ///
    /// - `ptr_` points to valid memory,
    ///
    /// - `ptr_ .. ptr+len` range is accessible memory,and is valid utf-8.
    ///
    /// - The data that `ptr_` points to must be valid for the lifetime of this `RStr<'a>`
    ///
    /// # Examples
    ///
    /// This function unsafely converts a `&str` to an `RStr<'_>`,
    /// equivalent to doing `RStr::from`.
    ///
    /// ```
    /// use abi_stable::std_types::RStr;
    ///
    /// fn convert(slice_:&str)->RStr<'_>{
    ///     unsafe{
    ///         RStr::from_raw_parts( slice_.as_ptr(), slice_.len() )
    ///     }
    /// }
    ///
    /// ```
    #[inline]
    pub const unsafe fn from_raw_parts(ptr_: *const u8, len: usize) -> Self {
        Self {
            inner: RSlice::from_raw_parts(ptr_, len),
        }
    }

    /// Converts `&'a str` to a `RStr<'a>`.
    ///
    /// # Example
    ///
    /// ```
    /// use abi_stable::std_types::RStr;
    ///
    /// assert_eq!(RStr::from_str("").as_str(), "");
    /// assert_eq!(RStr::from_str("Hello").as_str(), "Hello");
    /// assert_eq!(RStr::from_str("World").as_str(), "World");
    ///
    /// ```
    pub const fn from_str(s: &'a str) -> Self {
        unsafe{ Self::from_raw_parts( s.as_ptr(), s.len() ) }
    }

    /// For slicing `RStr`s.
    ///
    /// This is an inherent method instead of an implementation of the
    /// `std::ops::Index` trait because it does not return a reference.
    ///
    /// # Example
    ///
    /// ```
    /// use abi_stable::std_types::RStr;
    ///
    /// let str=RStr::from("What is that.");
    ///
    /// assert_eq!(str.slice(..),str);
    /// assert_eq!(str.slice(..4),RStr::from("What"));
    /// assert_eq!(str.slice(4..),RStr::from(" is that."));
    /// assert_eq!(str.slice(4..7),RStr::from(" is"));
    ///
    /// ```
    pub fn slice<I>(&self, i: I) -> RStr<'a>
    where
        str: Index<I, Output = str>,
    {
        self.as_str().index(i).into()
    }

    /// Accesses the underlying byte slice.
    ///
    /// # Example
    ///
    /// ```
    /// use abi_stable::std_types::{RSlice,RStr};
    ///
    /// let str=RStr::from("What is that.");
    /// let bytes=RSlice::from("What is that.".as_bytes());
    ///
    /// assert_eq!(str.as_rslice(),bytes);
    ///
    /// ```
    #[inline]
    pub const fn as_rslice(&self) -> RSlice<'a, u8> {
        self.inner
    }

    /// Casts this `RStr<'a>` to a `&'a str`.
    ///
    /// # Example
    ///
    /// ```
    /// use abi_stable::std_types::RStr;
    ///
    /// let str="What is that.";
    /// assert_eq!(RStr::from(str).as_str(),str);
    ///
    /// ```
    #[inline]
    pub fn as_str(&self) -> &'a str {
        unsafe { str::from_utf8_unchecked(self.inner.as_slice()) }
    }

    /// Gets a raw pointer to the start of the string slice.
    pub const fn as_ptr(&self) -> *const u8{
        self.inner.as_ptr()
    }

    /// Gets the length(in bytes) of this `RStr<'a>`.
    ///
    /// # Example
    ///
    /// ```
    /// use abi_stable::std_types::RStr;
    ///
    /// assert_eq!(RStr::from("").len(),0);
    /// assert_eq!(RStr::from("a").len(),1);
    /// assert_eq!(RStr::from("What").len(),4);
    ///
    /// ```
    #[inline]
    pub const fn len(&self) -> usize {
        self.inner.len()
    }

    /// Queries whether this RStr is empty.
    ///
    /// # Example
    ///
    /// ```
    /// use abi_stable::std_types::RStr;
    ///
    /// assert_eq!(RStr::from("").is_empty(),true);
    /// assert_eq!(RStr::from("a").is_empty(),false);
    /// assert_eq!(RStr::from("What").is_empty(),false);
    ///
    /// ```
    pub const fn is_empty(&self)->bool{
        self.inner.is_empty()
    }
}

unsafe impl<'a> Send for RStr<'a> {}
unsafe impl<'a> Sync for RStr<'a> {}

impl<'a> Default for RStr<'a> {
    fn default() -> Self {
        Self::EMPTY
    }
}

impl<'a> Deref for RStr<'a> {
    type Target = str;

    #[inline]
    fn deref(&self) -> &Self::Target {
        self.as_str()
    }
}

////////////////////////////////

impl<'a> Into<Cow<'a, str>> for RStr<'a> {
    fn into(self) -> Cow<'a, str> {
        self.as_str().into()
    }
}

impl_into_rust_repr! {
    impl['a] Into<&'a str> for RStr<'a> {
        fn(this){
            this.as_str()
        }
    }
}

impl<'a> Into<String> for RStr<'a> {
    fn into(self) -> String {
        self.as_str().into()
    }
}

impl<'a> Into<RString> for RStr<'a> {
    fn into(self) -> RString {
        self.as_str().into()
    }
}

impl_from_rust_repr! {
    impl['a] From<&'a str> for RStr<'a> {
        fn(this){
            RStr {
                inner: this.as_bytes().into(),
            }
        }
    }
}

////////////////////////////////

impl<'a> Borrow<str> for RStr<'a>{
    fn borrow(&self)->&str{
        self
    }
}

impl AsRef<str> for RStr<'_>{
    fn as_ref(&self)->&str{
        self
    }
}

impl AsRef<[u8]> for RStr<'_>{
    fn as_ref(&self)->&[u8]{
        self.as_bytes()
    }
}

////////////////////////////////

impl Display for RStr<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        Display::fmt(self.as_str(), f)
    }
}

impl<'de> Deserialize<'de> for RStr<'de> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        <&'de str as Deserialize<'de>>::deserialize(deserializer).map(Self::from)
    }
}

impl<'a> Serialize for RStr<'a> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        self.as_str().serialize(serializer)
    }
}

#[allow(dead_code)]
type Str<'a> = &'a str;

shared_impls! {
    mod=slice_impls
    new_type=RStr['a][],
    original_type=Str,
}

////////////////////////////////////////////////////

//#[cfg(test)]
#[cfg(all(test,not(feature="only_new_tests")))]
mod test {
    use super::*;

    #[test]
    fn from_to_str() {
        let a = "what the hell";
        let b = RStr::from_str(a);

        assert_eq!(a, &*b);
    }
}
