//! Plain string. //! //! String types defined here are almost same as std string types. enum PlainStrSpec {} impl validated_slice::SliceSpec for PlainStrSpec { type Custom = PlainStr; type Inner = str; type Error = std::convert::Infallible; #[inline] fn validate(_: &Self::Inner) -> Result<(), Self::Error> { Ok(()) } validated_slice::impl_slice_spec_methods! { field=0; methods=[ as_inner, as_inner_mut, from_inner_unchecked, from_inner_unchecked_mut, ]; } } /// Plain string slice. // `#[repr(transparent)]` or `#[repr(C)]` is required. // Without it, generated codes would be unsound. // // You can use `#[derive(Debug, PartialEq, PartialOrd)]` here, but in this example they are // implemented by macros in `validated_slice`. #[repr(transparent)] #[derive(Eq, Ord, Hash)] pub struct PlainStr(str); validated_slice::impl_std_traits_for_slice! { Spec { spec: PlainStrSpec, custom: PlainStr, inner: str, error: std::convert::Infallible, }; // AsMut for PlainStr // NOTE: `AsMut<[u8]> for str` is not implemented. //{ AsMut }; // AsMut for PlainStr { AsMut<{Custom}> }; // AsRef<[u8]> for PlainStr { AsRef<[u8]> }; // AsRef for PlainStr { AsRef }; // AsRef for PlainStr { AsRef<{Custom}> }; // From<&'_ str> for &'_ PlainStr { From<&{Inner}> for &{Custom} }; // From<&'_ mut str> for &'_ mut PlainStr { From<&mut {Inner}> for &mut {Custom} }; // From<&'_ PlainStr> for &'_ str { From<&{Custom}> for &{Inner} }; // From<&'_ mut PlainStr> for &'_ mut str { From<&mut {Custom}> for &mut {Inner} }; // From<&'_ PlainStr> for Arc { From<&{Custom}> for Arc<{Custom}> }; // From<&'_ PlainStr> for Box { From<&{Custom}> for Box<{Custom}> }; // From<&'_ PlainStr> for Rc { From<&{Custom}> for Rc<{Custom}> }; // Default for &'_ PlainStr { Default for &{Custom} }; // Default for &'_ mut PlainStr { Default for &mut {Custom} }; // Debug for PlainStr { Debug }; // Display for PlainStr { Display }; // Deref for PlainStr { Deref }; // DerefMut for PlainStr { DerefMut }; } validated_slice::impl_cmp_for_slice! { Spec { spec: PlainStrSpec, custom: PlainStr, inner: str, base: Inner, }; Cmp { PartialEq, PartialOrd }; // { lhs, rhs }. { ({Custom}), ({Custom}) }; { ({Custom}), (&{Custom}), rev }; // NOTE: This requires `std::borrow::ToOwned for PlainStr`. { ({Custom}), (Cow<{Custom}>), rev }; { ({Custom}), ({Inner}), rev }; { ({Custom}), (&{Inner}), rev }; { (&{Custom}), ({Inner}), rev }; { ({Custom}), (Cow<{Inner}>), rev }; { (&{Custom}), (Cow<{Inner}>), rev }; // NOTE: `{Inner}` should be local type to implement this. //{ ({Inner}), (Cow<{Custom}>), rev }; // NOTE: `{Inner}` should be local type to implement this. //{ (&{Inner}), (Cow<{Custom}>), rev }; } enum PlainBoxStrSpec {} impl validated_slice::OwnedSliceSpec for PlainBoxStrSpec { type Custom = PlainBoxStr; type Inner = Box; type Error = std::convert::Infallible; type SliceSpec = PlainStrSpec; type SliceCustom = PlainStr; type SliceInner = str; type SliceError = std::convert::Infallible; #[inline] fn convert_validation_error(e: Self::SliceError, _: Self::Inner) -> Self::Error { e } #[inline] fn as_slice_inner(s: &Self::Custom) -> &Self::SliceInner { &s.0 } #[inline] fn as_slice_inner_mut(s: &mut Self::Custom) -> &mut Self::SliceInner { &mut s.0 } #[inline] fn inner_as_slice_inner(s: &Self::Inner) -> &Self::SliceInner { s } #[inline] unsafe fn from_inner_unchecked(s: Self::Inner) -> Self::Custom { PlainBoxStr(s) } #[inline] fn into_inner(s: Self::Custom) -> Self::Inner { s.0 } } /// ASCII string boxed slice. #[derive(Default, Clone, Eq, Ord, Hash)] pub struct PlainBoxStr(Box); impl From for PlainBoxStr { fn from(s: PlainString) -> Self { Self(s.0.into_boxed_str()) } } validated_slice::impl_std_traits_for_owned_slice! { Spec { spec: PlainBoxStrSpec, custom: PlainBoxStr, inner: Box, error: std::convert::Infallible, slice_custom: PlainStr, slice_inner: str, slice_error: std::convert::Infallible, }; // AsMut for PlainBoxStr // NOTE: `AsMut<[u8]> for str` is not implemented. //{ AsMut }; // AsMut for PlainBoxStr { AsMut<{SliceCustom}> }; // AsRef<[u8]> for PlainBoxStr { AsRef<[u8]> }; // AsRef for PlainBoxStr { AsRef }; // AsRef for PlainBoxStr { AsRef<{SliceCustom}> }; // Borrow<[u8]> for PlainBoxStr // NOTE: `Borrow<[u8]> for str` is not implemented. //{ Borrow<[u8]> }; // Borrow for PlainBoxStr { Borrow }; // Borrow for PlainBoxStr { Borrow<{SliceCustom}> }; // BorrowMut for PlainBoxStr { BorrowMut }; // BorrowMut for PlainBoxStr { BorrowMut<{SliceCustom}> }; // ToOwned for PlainStr //{ ToOwned for {SliceCustom} }; // From<&'_ str> for PlainBoxStr { From<&{SliceInner}> }; // From<&'_ PlainStr> for PlainBoxStr { From<&{SliceCustom}> }; // From> for PlainBoxStr { From<{Inner}> }; // From for Box { From<{Custom}> for {Inner} }; // Default for PlainBoxStr // NOTE: Same as `#[derive(Default)]` in this case. //{ Default }; // Debug for PlainBoxStr { Debug }; // Display for PlainBoxStr { Display }; // Deref for PlainBoxStr { Deref }; // DerefMut for PlainBoxStr { DerefMut }; // FromStr for PlainBoxStr { FromStr }; } validated_slice::impl_cmp_for_owned_slice! { Spec { spec: PlainBoxStrSpec, custom: PlainBoxStr, inner: Box, slice_custom: PlainStr, slice_inner: str, base: Inner, }; Cmp { PartialEq, PartialOrd }; // { lhs, rhs }. { ({Custom}), ({Custom}) }; { ({Custom}), ({SliceCustom}), rev }; { ({Custom}), (&{SliceCustom}), rev }; //// NOTE: This requires `std::borrow::Borrow for PlainBoxStr`. { ({Custom}), (Cow<{SliceCustom}>), rev }; { ({Custom}), ({Inner}), rev }; { ({Custom}), ({SliceInner}), rev }; { ({Custom}), (&{SliceInner}), rev }; { ({Custom}), (Cow<{SliceInner}>), rev }; { ({Inner}), ({SliceCustom}), rev }; { ({Inner}), (&{SliceCustom}), rev }; } enum PlainStringSpec {} impl validated_slice::OwnedSliceSpec for PlainStringSpec { type Custom = PlainString; type Inner = String; type Error = std::convert::Infallible; type SliceSpec = PlainStrSpec; type SliceCustom = PlainStr; type SliceInner = str; type SliceError = std::convert::Infallible; #[inline] fn convert_validation_error(e: Self::SliceError, _: Self::Inner) -> Self::Error { e } #[inline] fn as_slice_inner(s: &Self::Custom) -> &Self::SliceInner { &s.0 } #[inline] fn as_slice_inner_mut(s: &mut Self::Custom) -> &mut Self::SliceInner { &mut s.0 } #[inline] fn inner_as_slice_inner(s: &Self::Inner) -> &Self::SliceInner { s } #[inline] unsafe fn from_inner_unchecked(s: Self::Inner) -> Self::Custom { PlainString(s) } #[inline] fn into_inner(s: Self::Custom) -> Self::Inner { s.0 } } /// ASCII string boxed slice. #[derive(Default, Clone, Eq, Ord, Hash)] pub struct PlainString(String); impl From for PlainString { fn from(s: PlainBoxStr) -> Self { Self(s.0.into()) } } validated_slice::impl_std_traits_for_owned_slice! { Spec { spec: PlainStringSpec, custom: PlainString, inner: String, error: std::convert::Infallible, slice_custom: PlainStr, slice_inner: str, slice_error: std::convert::Infallible, }; // AsMut for PlainString // NOTE: `AsMut<[u8]> for str` is not implemented. //{ AsMut }; // AsMut for PlainString { AsMut<{SliceCustom}> }; // AsRef<[u8]> for PlainString { AsRef<[u8]> }; // AsRef for PlainString { AsRef }; // AsRef for PlainString { AsRef<{SliceCustom}> }; // Borrow<[u8]> for PlainString // NOTE: `Borrow<[u8]> for str` is not implemented. //{ Borrow<[u8]> }; // Borrow for PlainString { Borrow }; // Borrow for PlainString { Borrow<{SliceCustom}> }; // BorrowMut for PlainString { BorrowMut<{SliceCustom}> }; // ToOwned for PlainStr { ToOwned for {SliceCustom} }; // From for PlainString { From<{Inner}> }; // From<&'_ str> for PlainString { From<&{SliceInner}> }; // From<&'_ PlainStr> for PlainString { From<&{SliceCustom}> }; // From for String { From<{Custom}> for {Inner} }; // Default for PlainString // NOTE: Same as `#[derive(Default)]` in this case. //{ Default }; // Debug for PlainString { Debug }; // Display for PlainString { Display }; // Deref for PlainString { Deref }; // DerefMut for PlainString { DerefMut }; // FromStr for PlainString { FromStr }; } validated_slice::impl_cmp_for_owned_slice! { Spec { spec: PlainStringSpec, custom: PlainString, inner: String, slice_custom: PlainStr, slice_inner: str, base: Inner, }; Cmp { PartialEq, PartialOrd }; // This is same as `#[derive(PartialEq, PartialOrd)]`. { ({Custom}), ({Custom}) }; { ({Custom}), ({SliceCustom}), rev }; { ({Custom}), (&{SliceCustom}), rev }; //// NOTE: This requires `std::borrow::Borrow for PlainString`. { ({Custom}), (Cow<{SliceCustom}>), rev }; { ({Custom}), ({Inner}), rev }; { ({Custom}), ({SliceInner}), rev }; { ({Custom}), (&{SliceInner}), rev }; { ({Custom}), (Cow<{SliceInner}>), rev }; { ({Inner}), ({SliceCustom}), rev }; { ({Inner}), (&{SliceCustom}), rev }; } #[cfg(test)] mod plain_str { use super::*; #[test] fn as_ref() where PlainStr: AsRef<[u8]>, PlainStr: AsRef, PlainStr: AsRef, PlainStr: AsMut, { } #[test] fn partial_eq_custom() where PlainStr: PartialEq, for<'a> PlainStr: PartialEq<&'a PlainStr>, for<'a> &'a PlainStr: PartialEq, for<'a> PlainStr: PartialEq>, for<'a> std::borrow::Cow<'a, PlainStr>: PartialEq>, { } #[test] fn partial_eq_inner() where PlainStr: PartialEq, str: PartialEq, for<'a> PlainStr: PartialEq<&'a str>, for<'a> &'a str: PartialEq, for<'a> &'a PlainStr: PartialEq, for<'a> str: PartialEq<&'a PlainStr>, for<'a> PlainStr: PartialEq>, for<'a> std::borrow::Cow<'a, str>: PartialEq, for<'a, 'b> &'b PlainStr: PartialEq>, for<'a, 'b> std::borrow::Cow<'a, str>: PartialEq<&'b PlainStr>, { } #[test] fn from() where for<'a> &'a PlainStr: From<&'a str>, for<'a> &'a mut PlainStr: From<&'a mut str>, for<'a> &'a str: From<&'a PlainStr>, for<'a> &'a mut str: From<&'a mut PlainStr>, { } #[test] fn from_smart_ptr() where for<'a> std::sync::Arc: From<&'a PlainStr>, for<'a> Box: From<&'a PlainStr>, for<'a> std::rc::Rc: From<&'a PlainStr>, { } #[test] fn default() where for<'a> &'a PlainStr: Default, for<'a> &'a mut PlainStr: Default, { } #[test] fn fmt() where PlainStr: std::fmt::Debug, PlainStr: std::fmt::Display, { let sample_raw = "text"; let sample_plain = <&PlainStr>::from(sample_raw); assert_eq!(format!("{:?}", sample_plain), "\"text\""); assert_eq!(format!("{}", sample_plain), sample_raw); } #[test] fn deref() where PlainStr: std::ops::Deref, PlainStr: std::ops::DerefMut, { } } #[cfg(test)] mod plain_box_str { use super::*; #[test] fn as_ref() where PlainBoxStr: AsRef<[u8]>, PlainBoxStr: AsRef, PlainBoxStr: AsRef, PlainBoxStr: AsMut, { } #[test] fn borrow() where PlainBoxStr: std::borrow::Borrow, PlainBoxStr: std::borrow::Borrow, { } #[test] fn borrow_mut() where PlainBoxStr: std::borrow::BorrowMut, PlainBoxStr: std::borrow::BorrowMut, { } #[test] fn partial_eq_custom() where PlainBoxStr: PartialEq, PlainBoxStr: PartialEq, PlainStr: PartialEq, for<'a> PlainBoxStr: PartialEq<&'a PlainStr>, for<'a> &'a PlainStr: PartialEq, for<'a> PlainBoxStr: PartialEq>, for<'a> std::borrow::Cow<'a, PlainStr>: PartialEq, { } #[test] fn partial_eq_inner() where PlainBoxStr: PartialEq, str: PartialEq, for<'a> PlainBoxStr: PartialEq<&'a str>, for<'a> &'a str: PartialEq, for<'a> PlainBoxStr: PartialEq>, for<'a> std::borrow::Cow<'a, str>: PartialEq, Box: PartialEq, PlainStr: PartialEq>, for<'a> Box: PartialEq<&'a PlainStr>, for<'a> &'a PlainStr: PartialEq>, { } #[test] fn partial_ord_custom() where PlainBoxStr: PartialOrd, PlainBoxStr: PartialOrd, PlainStr: PartialOrd, for<'a> PlainBoxStr: PartialOrd<&'a PlainStr>, for<'a> &'a PlainStr: PartialOrd, for<'a> PlainBoxStr: PartialOrd>, for<'a> std::borrow::Cow<'a, PlainStr>: PartialOrd, { } #[test] fn partial_ord_inner() where PlainBoxStr: PartialOrd, str: PartialOrd, for<'a> PlainBoxStr: PartialOrd<&'a str>, for<'a> &'a str: PartialOrd, for<'a> PlainBoxStr: PartialOrd>, for<'a> std::borrow::Cow<'a, str>: PartialOrd, Box: PartialOrd, PlainStr: PartialOrd>, for<'a> Box: PartialOrd<&'a PlainStr>, for<'a> &'a PlainStr: PartialOrd>, { } #[test] fn from() where for<'a> PlainBoxStr: From<&'a str>, for<'a> PlainBoxStr: From<&'a PlainStr>, PlainBoxStr: From>, Box: From, { } #[test] fn fmt() where PlainBoxStr: std::fmt::Debug, PlainBoxStr: std::fmt::Display, { let sample_raw = "text"; let sample_plain = PlainBoxStr::from(sample_raw); assert_eq!(format!("{:?}", sample_plain), "\"text\""); assert_eq!(format!("{}", sample_plain), sample_raw); let sample_plain_borrowed = <&PlainStr>::from(sample_raw); assert_eq!( format!("{:?}", sample_plain), format!("{:?}", sample_plain_borrowed) ); assert_eq!( format!("{}", sample_plain), format!("{}", sample_plain_borrowed) ); } #[test] fn deref() where PlainBoxStr: std::ops::Deref, { } #[test] fn deref_mut() where PlainBoxStr: std::ops::DerefMut, { } #[test] fn from_str() where PlainBoxStr: std::str::FromStr, { } } #[cfg(test)] mod plain_string { use super::*; #[test] fn as_ref() where PlainString: AsRef<[u8]>, PlainString: AsRef, PlainString: AsRef, PlainString: AsMut, { } #[test] fn borrow() where PlainString: std::borrow::Borrow, PlainString: std::borrow::Borrow, { } #[test] fn borrow_mut() where PlainString: std::borrow::BorrowMut, { } #[test] fn to_owned() where PlainStr: std::borrow::ToOwned, { } #[test] fn partial_eq_custom() where PlainString: PartialEq, PlainString: PartialEq, PlainStr: PartialEq, for<'a> PlainString: PartialEq<&'a PlainStr>, for<'a> &'a PlainStr: PartialEq, for<'a> PlainString: PartialEq>, for<'a> std::borrow::Cow<'a, PlainStr>: PartialEq, { } #[test] fn partial_eq_inner() where PlainString: PartialEq, str: PartialEq, for<'a> PlainString: PartialEq<&'a str>, for<'a> &'a str: PartialEq, for<'a> PlainString: PartialEq>, for<'a> std::borrow::Cow<'a, str>: PartialEq, String: PartialEq, PlainStr: PartialEq, for<'a> String: PartialEq<&'a PlainStr>, for<'a> &'a PlainStr: PartialEq, { } #[test] fn partial_ord_custom() where PlainString: PartialOrd, PlainString: PartialOrd, PlainStr: PartialOrd, for<'a> PlainString: PartialOrd<&'a PlainStr>, for<'a> &'a PlainStr: PartialOrd, for<'a> PlainString: PartialOrd>, for<'a> std::borrow::Cow<'a, PlainStr>: PartialOrd, { } #[test] fn partial_ord_inner() where PlainString: PartialOrd, str: PartialOrd, for<'a> PlainString: PartialOrd<&'a str>, for<'a> &'a str: PartialOrd, for<'a> PlainString: PartialOrd>, for<'a> std::borrow::Cow<'a, str>: PartialOrd, String: PartialOrd, PlainStr: PartialOrd, for<'a> String: PartialOrd<&'a PlainStr>, for<'a> &'a PlainStr: PartialOrd, { } #[test] fn from() where for<'a> PlainString: From<&'a str>, for<'a> PlainString: From<&'a PlainStr>, PlainString: From, String: From, { } #[test] fn fmt() where PlainString: std::fmt::Debug, PlainString: std::fmt::Display, { let sample_raw = "text"; let sample_plain = PlainString::from(sample_raw); assert_eq!(format!("{:?}", sample_plain), "\"text\""); assert_eq!(format!("{}", sample_plain), sample_raw); let sample_plain_borrowed = <&PlainStr>::from(sample_raw); assert_eq!( format!("{:?}", sample_plain), format!("{:?}", sample_plain_borrowed) ); assert_eq!( format!("{}", sample_plain), format!("{}", sample_plain_borrowed) ); } #[test] fn deref() where PlainString: std::ops::Deref, { } #[test] fn deref_mut() where PlainString: std::ops::DerefMut, { } #[test] fn from_str() where PlainString: std::str::FromStr, { } }