2 个版本
0.1.1 | 2019年5月3日 |
---|---|
0.1.0 | 2019年5月2日 |
#50 in #owned
每月 70 次下载
88KB
1.5K SLoC
custom-slice
通过过程宏轻松定义自定义切片类型(无需用户手动编写不安全代码)。
使用方法
考虑以下情况,您想定义以下切片类型
/// Owned slice.
// Sized type.
pub struct Owned(OwnedInner);
/// Borrowed slice.
// Unsized slice type.
pub struct Slice(SliceInner);
impl std::borrow::Borrow<Slice> for Owned { /* .. */ }
impl std::borrow::ToOwned for Slice {
type Owned = Owned;
// ..
}
例如,如果 Owned
是 String
且 Slice
是 str
,OwnedInner
是 Vec<u8>
且 SliceInner
是 [u8]
。
基本
custom_slice_macros::define_slice_types_pair! {
/// Owned slice.
#[custom_slice(owned)]
pub struct Owned(OwnedInner);
/// Borrowed slice.
#[repr(transparent)]
#[custom_slice(slice)]
pub struct Slice(SliceInner);
}
通过这种方式,自动实现了 std::borrow::Borrow
和 std::borrow::ToOwned
。
注意
- 切片类型需要
#[repr(transparent)]
或#[repr(C)]
。 - 如果类型不是
#[custom_slice(..)]
样式,则会发出类型属性。- 可以为类型指定
#[derive(Debug, Clone, Copy, ..)]
。
- 可以为类型指定
- 可见性将不会被修改。
- 除了
pub
之外,可以使用任何有效的可见性(如pub(crate)
或无)。
- 除了
构造函数、错误和验证器
可以为构造函数指定验证函数和错误类型。
这对于值有限(与内部类型相比)的类型很有用。例如,Vec<u8>
可以包含任何二进制数据,但String
可以包含有效的UTF-8序列。
- 指定构造函数名称、可见性和不安全。以下所有属性都是可选的。
#[custom_slice(new_unchecked = ..)]
:不带验证的构造函数。- 这不需要验证器。
- 这返回
Owned
。
#[custom_slice(new_checked = ..)]
:带验证的构造函数。- 这需要验证器。
- 这返回
Result<Owned, _>
。
#[custom_slice(new_unchecked_mut = ..)]
:不带验证的构造函数。- 这不需要验证器。
- 仅适用于切片类型。
- 这返回
&mut Slice
。
#[custom_slice(new_checked_mut = ..)]
:带验证的构造函数。- 这需要验证器。
- 仅适用于切片类型。
- 这返回
Result<&mut Slice, _>
。
- 指定验证函数。
- 可选。
- 验证函数的名称可以是任何有效的名称,但应该在宏
define_slice_types_pair!
中定义,并且应该具有属性#[custom_slice(validator)]
。 - 返回类型应为
std::result::Result<(), _>
。
- 指定错误类型和映射函数。
- 使用
#[custom_slice(error(type = "ErrorTypeName"))]
。 - 如果您想返回修改后的错误,请使用
#[custom_slice(error(type = "ErrorTypeName"))]
。 #[custom_slice(error(type = "ErrorTypeName"))]
。#[custom_slice(error(type = "ErrorTypeName"))]
。
- 使用
#[custom_slice(error(type = "ErrorTypeName"))]
。
custom_slice_macros::define_slice_types_pair! {
/// Owned slice.
// Assume `owned_inner: OwnedInner`.
#[custom_slice(owned)]
//let _: Owned = Owned::new(owned_inner);
#[custom_slice(new_unchecked = "fn new")]
pub struct Owned(OwnedInner);
/// Borrowed slice.
#[repr(transparent)]
// Assume `slice_inner_ref: &Slice` and `slice_inner_mut: &mut Slice`.
#[custom_slice(slice)]
//let _: &Slice = Slice::new(slice_inner_ref);
#[custom_slice(new = "fn new")]
//let _: &mut Slice = Slice::new_mut(slice_inner_mut);
#[custom_slice(new_mut = "fn new_mut")]
pub struct Slice(SliceInner);
}
#[custom_slice(error(type = "ErrorTypeName"))]
。
custom_slice_macros::define_slice_types_pair! {
/// Owned slice.
// Assume `owned_inner: OwnedInner`.
#[custom_slice(owned)]
//let _: Owned = unsafe { Owned::new_unchecked(owned_inner) };
#[custom_slice(new_unchecked = "unsafe fn new_unchecked")]
//let _: Result<Owned, ErrorWithInner> = Owned::new(owned_inner);
#[custom_slice(new_checked = "pub fn new")]
#[custom_slice(error(
type = "ErrorWithInner",
map = "{|e, v| Error { error: e, value: v } }"
))]
pub struct Owned(OwnedInner);
/// Borrowed slice.
#[repr(transparent)]
// Assume `slice_inner_ref: &Slice` and `slice_inner_mut: &mut Slice`.
#[custom_slice(slice)]
//let _: &Slice = unsafe { Slice::new_unchecked(slice_inner_ref) };
#[custom_slice(new_unchecked = "unsafe fn new_unchecked")]
//let _: &mut Slice = unsafe { Slice::new_unchecked_mut(slice_inner_mut) };
#[custom_slice(new_unchecked_mut = "unsafe fn new_unchecked_mut")]
//let _: Result<&Slice, Error> = Slice::new(slice_inner_ref);
#[custom_slice(new_checked = "pub fn new")]
//let _: Result<&mut Slice, Error> = Slice::new_mut(slice_inner_mut);
#[custom_slice(new_checked_mut = "pub fn new_mut")]
#[custom_slice(error(type = "Error"))]
pub struct Slice(SliceInner);
/// Validates the given data.
///
/// Returns `Ok(())` for valid data, `Err(_)` for invalid data.
#[custom_slice(validator)]
fn validate(s: &SliceInner) -> Result<(), Error> {
/* Do the validation. */
}
}
可以定义具有有意义的名称的内嵌类型的访问器。
指定访问器名称、可见性和不安全性。下面的所有属性都是可选的。
custom_slice_macros::define_slice_types_pair! {
/// Owned slice.
// Assume `owned: Owned` and `mut owned_mut: Owned`.
#[custom_slice(owned)]
//let _: &OwnedInner = owned.get();
#[custom_slice(get_ref = "pub fn get")]
//let _: &mut OwnedInner = owned_mut.get_mut();
#[custom_slice(get_mut = "fn get_mut")]
//let _: OwnedInner = owned.into_inner();
#[custom_slice(into_inner = "pub fn into_inner")]
pub struct Owned(OwnedInner);
/// Borrowed slice.
// Assume `slice_ref: &Slice` and `slice_mut: &mut Slice`.
#[repr(transparent)]
#[custom_slice(slice)]
//let _: &SliceInner = slice_ref.get();
#[custom_slice(get_ref = "pub fn get")]
//let _: &mut SliceInner = slice_mut.get_mut();
#[custom_slice(get_mut = "fn get_mut")]
pub struct Slice(SliceInner);
}
#[custom_slice(error(type = "ErrorTypeName"))]
。- 此返回值为
&OwnedInner
或&SliceInner
。#[custom_slice(error(type = "ErrorTypeName"))]
。
#[custom_slice(error(type = "ErrorTypeName"))]
。- 此返回值为
&mut OwnedInner
或&mut SliceInner
。
- 此返回值为
#[custom_slice(into_inner = ..)]
:析构函数。- 此函数返回
OwnedInner
。 - 仅对拥有类型有效。
- 此函数返回
- 此返回值为
函数的注释和属性
在指定函数的属性(如 get_ref
和 new_unchecked
)中,您可以指定属性和注释。
例如
custom_slice_macros::define_slice_types_pair! {
/// Owned slice.
#[custom_slice(owned)]
#[custom_slice(get_ref = "#[allow(missing_docs)] pub fn get")]
#[custom_slice(get_mut = "#[deny(dead_code)] fn get_mut")]
#[custom_slice(into_inner = "
/// Extracts the inner owned slice.
pub fn into_inner
")]
pub struct Owned(OwnedInner);
/// Borrowed slice.
#[repr(transparent)]
#[custom_slice(slice)]
#[custom_slice(new_unchecked = "
/// Creates a new `Slice` without validation.
#[deprecated (since = \"0.2.0\", note = \"Use `new_checked`\")]
pub fn new_unchecked
")]
#[custom_slice(new_checked = "
/// Creates a new `Slice` if the given value is valid.
pub fn new_checked
")]
pub struct Slice(SliceInner);
}
派生特性
custom_slice_macros::define_slice_types_pair!
支持生成可能需要不安全操作的 impl。
custom_slice_macros::define_slice_types_pair! {
/// Owned slice.
#[custom_slice(owned)]
#[custom_slice(derive(BorrowMut, Deref, DerefMut))]
pub struct Owned(OwnedInner);
/// Borrowed slice.
#[repr(transparent)]
#[custom_slice(slice)]
#[custom_slice(derive(DefaultRef, DefaultRefMut))]
pub struct Slice(SliceInner);
}
以下派生目标可用
拥有类型的派生目标
std::borrow::*
impl std::borrow::BorrowMut<Slice> for Owned { /* .. */ }
std::cmp::*
PartialEq
:impl std::cmp::PartialEq<Owned> for Owned { /* .. */ }
- 需要
PartialEq<Slice> for Slice
。 - 通常使用
#[derive(PartialEq)]
作为其内部实现,但它使用#[custom_slice(derive(PartialEq))]
作为其内部实现。如果您为Slice
类型定义了自定义比较,则应使用#[custom_slice(derive(PartialEq))]
为Owned
类型。
- 需要
PartialEqBulk
:许多实现使用<Slice as PartialEq<Slice>>
。- 需要
PartialEq<Slice> for Slice
。 impl PartialEq<Slice> for Owned
impl PartialEq<Owned> for Slice
impl PartialEq<&Slice> for Owned
impl PartialEq<Owned> for &Slice
impl PartialEq<Cow<Slice>> for Owned
impl PartialEq<Owned> for Cow<Slice>
- 需要
PartialEqInnerBulk
:许多实现使用<SliceInner as PartialEq<SliceInner>>
。- 需要
PartialEq<SliceInner> for SliceInner
。 impl PartialEq<SliceInner> for Owned
impl PartialEq<Owned> for SliceInner
impl PartialEq<&SliceInner> for Owned
impl PartialEq<Owned> for &SliceInner
impl PartialEq<Cow<SliceInner>> for Owned
impl PartialEq<Owned> for Cow<SliceInner>
- 需要
PartialOrd
,PartialOrdBulk
,PartialOrdInnerBulk
:对应于PartialEq*
目标的PartialOrd
版本。- 需要相应的
PartialEq*
实现者。 - 请参阅相应
PartialEq*
的描述以获取详细信息。
- 需要相应的
std::转换::*
AsRefSlice
:为impl std::convert::AsRef<Slice> for Owned { /* .. */ }
- 需要
AsRef<SliceInner>: OwnedInner
。
- 需要
AsRefSliceInner
:impl std::convert::AsRef<SliceInner> for Owned { /* .. */ }
- 需要
AsRef<SliceInner>: OwnedInner
。
- 需要
AsMutSlice
:impl std::convert::AsMut<Slice> for Owned { /* .. */ }
- 需要满足
AsMut<SliceInner>: OwnedInner
。
- 需要满足
AsMutSliceInner
:impl std::convert::AsMut<SliceInner> for Owned { /* .. */ }
- 需要满足
AsMut<SliceInner>: OwnedInner
。
- 需要满足
FromInner
:impl std::convert::From<OwnedInner> for Owned { /* .. */ }
- 需要验证器不存在。
IntoInner
:impl std::convert::From<Owned> for OwnedInner { /* .. */ }
TryFromInner
:impl std::convert::TryFrom<OwnedInner> for Owned { /* .. */ }
- 需要验证器存在。
std::操作::*
Deref
:impl std::ops::Deref for Owned { type Target = Slice; /* .. */ }
DerefMut
:impl std::ops::DerefMut for Owned { /* .. */ }
- 需要
Deref<Target = Slice> for Owned
。
- 需要
为切片类型推导目标
std::cmp::*
PartialEqBulk
:许多实现使用<Slice as PartialEq<Slice>>
。- 需要
PartialEq<Slice> for Slice
。 impl PartialEq<&Slice> for Slice
impl PartialEq<Slice> for &Slice
impl PartialEq<Cow<Slice>> for Slice
impl PartialEq<Slice> for Cow<Slice>
- 需要
PartialEqInnerBulk
:许多实现使用<SliceInner as PartialEq<SliceInner>>
。- 需要
PartialEq<SliceInner> for SliceInner
。 impl PartialEq<SliceInner> for Slice
impl PartialEq<Slice> for SliceInner
impl PartialEq<&SliceInner> for Slice
impl PartialEq<Slice> for &SliceInner
impl PartialEq<OwnedInner> for Slice
impl PartialEq<Slice> for OwnedInner
impl PartialEq<Cow<SliceInner>> for Slice
impl PartialEq<Slice> for Cow<SliceInner>
impl PartialEq<SliceInner> for &Slice
impl PartialEq<&Slice> for SliceInner
impl PartialEq<OwnedInner> for &Slice
impl PartialEq<&Slice> for OwnedInner
impl PartialEq<Cow<SliceInner>> for &Slice
impl PartialEq<&Slice> for Cow<SliceInner>
- 需要
PartialOrdBulk、
PartialOrdInnerBulk
:PartialOrd
版本的对应PartialEq*
目标。- 需要相应的
PartialEq*
实现者。 - 请参阅相应
PartialEq*
的描述以获取详细信息。
- 需要相应的
std::转换::*
AsRefSlice
:impl std::convert::AsRef<Slice> for Slice { /* .. */ }
- 需要
AsRef<SliceInner>: SliceInner
。
- 需要
AsRefSliceInner
:impl std::convert::AsRef<SliceInner> for Slice { /* .. */ }
- 需要
AsRef<SliceInner>: SliceInner
。
- 需要
AsMutSlice
:impl std::convert::AsMut<Slice> for Slice { /* .. */ }
- 需要
AsMut<SliceInner>: SliceInner
。
- 需要
AsMutSliceInner
:impl std::convert::AsMut<SliceInner> for Slice { /* .. */ }
- 需要
AsMut<SliceInner>: SliceInner
。
- 需要
FromInner
:impl<'a> std::convert::From<&'a SliceInner> for &'a Slice { /* .. */ }
- 需要验证器不存在。
FromInnerMut
:impl<'a> std::convert::From<&'a mut SliceInner> for &'a mut Slice { /* .. */ }
- 需要验证器不存在。
IntoArc
:impl std::convert::From<&Slice> for std::sync::Arc<Slice> { /* .. */ }
- 需要
Arc<SliceInner>: From<&SliceInner>
.
- 需要
IntoBox
:impl std::convert::From<&Slice> for std::boxed::Box<Slice> { /* .. */ }
- 需要
Box<SliceInner>: From<&SliceInner>
.
- 需要
IntoRc
:impl std::convert::From<&Slice> for std::rc::Rc<Slice> { /* .. */ }
- 需要
Rc<SliceInner>: From<&SliceInner>
.
- 需要
TryFromInner
:impl<'a> std::convert::TryFrom<&'a SliceInner> for &'a Slice { /* .. */ }
- 需要验证器存在。
TryFromInnerMut
:impl<'a> std::convert::TryFrom<&'a mut SliceInner> for &'a mut Slice{/* .. */}
- 需要验证器存在。
std::默认::*
DefaultBox
:implstd::default::Default forBox<Slice>{/* .. */}
- 需要
Box<SliceInner>:Default
。
- 需要
DefaultRef
:implstd::default::Default for&Slice{/* .. */}
- 需要
&SliceInner:Default
。
- 需要
DefaultRefMut
:implstd::default::Default for&mut Slice{/* .. */}
- 需要
&mut SliceInner:Default
。
- 需要
std::操作::*
Deref
:implstd::ops::Deref forSlice{type Target = SliceInner;/* .. */}
DerefMut
:impl std::ops::DerefMut for Slice { /* .. */ }
- 需要
Deref<Target = SliceInner> for Slice
。
- 需要
许可证
根据您的选择,许可协议为以下之一:
- Apache License, Version 2.0, (LICENSE-APACHE.txt 或 https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT.txt 或 https://opensource.org/licenses/MIT)
。
贡献
除非您明确声明,否则根据 Apache-2.0 许可证定义的,您有意提交并包含在作品中的任何贡献,都将按上述方式双许可,不附加任何额外的条款或条件。
依赖
~2MB
~46K SLoC