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 Ownedimpl PartialEq<Owned> for Sliceimpl PartialEq<&Slice> for Ownedimpl PartialEq<Owned> for &Sliceimpl PartialEq<Cow<Slice>> for Ownedimpl PartialEq<Owned> for Cow<Slice>
- 需要
PartialEqInnerBulk:许多实现使用<SliceInner as PartialEq<SliceInner>>。- 需要
PartialEq<SliceInner> for SliceInner。 impl PartialEq<SliceInner> for Ownedimpl PartialEq<Owned> for SliceInnerimpl PartialEq<&SliceInner> for Ownedimpl PartialEq<Owned> for &SliceInnerimpl PartialEq<Cow<SliceInner>> for Ownedimpl 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 Sliceimpl PartialEq<Slice> for &Sliceimpl PartialEq<Cow<Slice>> for Sliceimpl PartialEq<Slice> for Cow<Slice>
- 需要
PartialEqInnerBulk:许多实现使用<SliceInner as PartialEq<SliceInner>>。- 需要
PartialEq<SliceInner> for SliceInner。 impl PartialEq<SliceInner> for Sliceimpl PartialEq<Slice> for SliceInnerimpl PartialEq<&SliceInner> for Sliceimpl PartialEq<Slice> for &SliceInnerimpl PartialEq<OwnedInner> for Sliceimpl PartialEq<Slice> for OwnedInnerimpl PartialEq<Cow<SliceInner>> for Sliceimpl PartialEq<Slice> for Cow<SliceInner>impl PartialEq<SliceInner> for &Sliceimpl PartialEq<&Slice> for SliceInnerimpl PartialEq<OwnedInner> for &Sliceimpl PartialEq<&Slice> for OwnedInnerimpl PartialEq<Cow<SliceInner>> for &Sliceimpl 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://apache.ac.cn/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT.txt 或 https://open-source.org.cn/licenses/MIT)
。
贡献
除非您明确声明,否则根据 Apache-2.0 许可证定义的,您有意提交并包含在作品中的任何贡献,都将按上述方式双许可,不附加任何额外的条款或条件。
依赖
~2MB
~46K SLoC