macro_rules! impl_std_traits_for_owned_slice {
(
Std {
core: $core:ident,
alloc: $alloc:ident,
};
Spec {
spec: $spec:ty,
custom: $custom:ty,
inner: $inner:ty,
error: $error:ty,
slice_custom: $slice_custom:ty,
slice_inner: $slice_inner:ty,
slice_error: $slice_error:ty,
};
$({$($rest:tt)*});* $(;)?
) => { ... };
(
Spec {
spec: $spec:ty,
custom: $custom:ty,
inner: $inner:ty,
error: $error:ty,
slice_custom: $slice_custom:ty,
slice_inner: $slice_inner:ty,
slice_error: $slice_error:ty,
};
$({$($rest:tt)*});* $(;)?
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ Borrow<{SliceCustom}> ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ Borrow<$param:ty> ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ BorrowMut<{SliceCustom}> ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ BorrowMut<$param:ty> ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ ToOwned<Owned = {Custom}> for {SliceCustom} ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ AsMut<{SliceCustom}> ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ AsMut<$param:ty> ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ AsRef<{SliceCustom}> ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ AsRef<$param:ty> ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ From<&{SliceInner}> ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ From<&{SliceCustom}> ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ From<{Inner}> ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ From<{Custom}> for {Inner} ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ TryFrom<&{SliceInner}> ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ TryFrom<{Inner}> ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ Default ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ Debug ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ Display ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ Deref<Target = {SliceCustom}> ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ DerefMut<Target = {SliceCustom}> ];
) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ FromStr ];
) => { ... };
(@conv:as_slice, $spec:ty, $slice_spec:ty, $owned_ref:expr) => { ... };
(@conv:as_mut_slice, $spec:ty, $slice_spec:ty, $owned_ref:expr) => { ... };
(
@impl; ({$core:ident, $alloc:ident}, $spec:ty, $custom:ty, $inner:ty, $error:ty,
$slice_spec:ty, $slice_custom:ty, $slice_inner:ty, $slice_error:ty);
rest=[ $($rest:tt)* ];
) => { ... };
}Expand description
Implements std traits for the given custom slice type.
To implement PartialEq and PartialOrd, use impl_cmp_for_owned_slice! macro.
§Usage
§Examples
Assume you want to implement str and String types manually by yourself.
Then you will have the type definitions below:
/// My `str` type.
#[repr(transparent)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MyStr([u8]);
/// Spec for `MyStr` type.
enum MyStrSpec {}
impl validated_slice::SliceSpec for MyStrSpec {
// My `str` type.
type Custom = MyStr;
// Backend type of `MyStr`.
type Inner = [u8];
// My `std::str::Utf8Error`.
type Error = MyUtf8Error;
/* ... and methods. */
}
/// My `String` type.
#[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AsciiString(Vec<u8>);
/// Spec for `MyString` type.
enum MyStringSpec {}
impl validated_slice::OwnedSliceSpec for MyStringSpec {
// My `String` type.
type Custom = MyString;
// Backend type of `MyString`.
type Inner = Vec<u8>;
// My `std::str::Utf8Error`.
type Error = MyFromUtf8Error;
// Spec of custom borrowed slice type, `MyStr` for this example.
type SliceSpec = MyStrSpec;
// Custom borrowed slice type.
// This should be same as `MyStrSpec::Custom`.
type SliceCustom = MyStr;
// Backend type of the custom borrowed slice type.
// This should be same as `MyStrSpec::Inner`.
type SliceInner = [u8];
// My `std::string::FromUtf8Error`.
// This should be same as `MyStrSpec::Error`.
type SliceError = MyFromUtf8Error;
/* ... and methods. */
}Then you can implement std traits as below:
validated_slice::impl_std_traits_for_owned_slice! {
// `Std` is omissible.
Std {
// Module identifier of `core` crate.
// Default is `std`.
core: core,
// Module identifier of `alloc` crate.
// Default is `std`.
alloc: alloc,
};
Spec {
spec: MyStringSpec,
custom: MyString,
inner: Vec<u8>,
error: MyFromUtf8Error,
slice_custom: MyStr,
slice_inner: [u8],
slice_error: MyUtf8Error,
};
{ AsRef<[u8]> };
{ AsRef<str> };
{ AsRef<{Custom}> };
{ ToOwned<Owned = {Custom}> for {SliceCustom} };
{ TryFrom<&{SliceInner}> };
{ TryFrom<{Inner}> };
/* ... and more traits you want! */
}§Core and alloc
For no_std use, the macro uses custom core and alloc crate if given.
You can support both nostd and non-nostd environment as below:
// Use `std` when available.
#[cfg(feature = "std")]
use alloc as std;
// Use external `alloc` crate when nostd.
#[cfg(not(feature = "std"))]
use alloc;
validated_slice::impl_std_traits_for_owned_slice! {
Std {
core: core,
alloc: alloc,
};
Spec { /* ... */ };
/* ... */
}§Type names
As type name, you can use {Custom} and {Inner} instead of a real type name.
They are replaced to the specified custom and inner types.
Arc<ty>, Box<ty>, Cow<ty>, and Rc<ty> will be also replaced to std::sync::Arc<ty>,
std::boxed::Box<ty>, std::borrow::Cow<'_, ty>, and std::rc::Rc<ty>, respectively.
They are checked symbolically, so they cannot be specified by type aliases, or
path names such as std::sync::Arc<ty>.
§Supported trait impls
NOTE: To implemente PartialEq and PartialOrd, use impl_cmp_for_owned_slice! macro.
Each trait impl is specified by { TraitName<TyParams> for TyImplTarget }; format.
<TyParams> part and for TyImplTarget part is optional.
Default impl target is {Custom}, and it should NOT be specified explicitly.
Explicit for {Custom} is not supported and will cause compile error.
Supported trait impls are:
std::borrow{ Borrow<{SliceCustom}> };{ Borrow<any_ty> };{ BorrowMut<{SliceCustom}> };{ BorrowMut<any_ty> };{ ToOwned<Owned = {Custom}> for {SliceCustom} };
std::convert{ AsMut<{SliceCustom}> };{ AsMut<any_ty> };{ AsRef<{SliceCustom}> };{ AsRef<any_ty> };{ From<&{SliceInner}> };{ From<&{SliceCustom}> };{ From<{Inner}> };{ From<{Custom}> for {Inner} };{ TryFrom<&{SliceInner}> };{ TryFrom<{Inner}> };
std::default{ Default };- Note that this redirects to trait impls for
{SliceCustom}, rather than for{Inner}or{SliceInner}.
- Note that this redirects to trait impls for
std::fmt{ Debug };{ Display };- Note that these redirects to trait impls for
{SliceCustom}, rather than for{Inner}or{SliceInner}.
std::ops{ Deref<Target = {SliceCustom}> };{ DerefMut<Target = {SliceCustom}> };
std::str{ FromStr };