#slice #owned #define #type #pair #macro #string

custom-slice-macros

定义自定义切片类型的实用工具

2 个版本

0.1.1 2019年5月3日
0.1.0 2019年5月2日

#50 in #owned

Download history 6/week @ 2024-03-09 1/week @ 2024-03-16 33/week @ 2024-03-30 9/week @ 2024-04-06

每月 70 次下载

MIT/Apache

88KB
1.5K SLoC

custom-slice

Build Status Minimum rustc version: 1.34

custom-slice-macros: 最新版本 文档

通过过程宏轻松定义自定义切片类型(无需用户手动编写不安全代码)。

使用方法

考虑以下情况,您想定义以下切片类型

/// 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;

    // ..
}

例如,如果 OwnedStringSlicestrOwnedInnerVec<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::Borrowstd::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_refnew_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>
    • PartialOrdPartialOrdBulkPartialOrdInnerBulk:对应于 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 { /* .. */ }
    • TryFromInnerimpl std::convert::TryFrom<OwnedInner> for Owned { /* .. */ }
      • 需要验证器存在。
  • std::操作::*
    • Derefimpl std::ops::Deref for Owned { type Target = Slice; /* .. */ }
    • DerefMutimpl 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>
    • PartialOrdBulkPartialOrdInnerBulkPartialOrd 版本的对应 PartialEq* 目标。
      • 需要相应的 PartialEq* 实现者。
      • 请参阅相应 PartialEq* 的描述以获取详细信息。
  • std::转换::*
    • AsRefSliceimpl std::convert::AsRef<Slice> for Slice { /* .. */ }
      • 需要 AsRef<SliceInner>: SliceInner
    • AsRefSliceInnerimpl std::convert::AsRef<SliceInner> for Slice { /* .. */ }
      • 需要 AsRef<SliceInner>: SliceInner
    • AsMutSliceimpl std::convert::AsMut<Slice> for Slice { /* .. */ }
      • 需要 AsMut<SliceInner>: SliceInner
    • AsMutSliceInnerimpl std::convert::AsMut<SliceInner> for Slice { /* .. */ }
      • 需要 AsMut<SliceInner>: SliceInner
    • FromInnerimpl<'a> std::convert::From<&'a SliceInner> for &'a Slice { /* .. */ }
      • 需要验证器不存在。
    • FromInnerMutimpl<'a> std::convert::From<&'a mut SliceInner> for &'a mut Slice { /* .. */ }
      • 需要验证器不存在。
    • IntoArcimpl 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 { /* .. */ }
      • 需要验证器存在。
    • TryFromInnerMutimpl<'a> std::convert::TryFrom<&'a mut SliceInner> for &'a mut Slice{/* .. */}
      • 需要验证器存在。
  • std::默认::*
    • DefaultBoximplstd::default::Default forBox<Slice>{/* .. */}
      • 需要 Box<SliceInner>:Default
    • DefaultRefimplstd::default::Default for&Slice{/* .. */}
      • 需要 &SliceInner:Default
    • DefaultRefMutimplstd::default::Default for&mut Slice{/* .. */}
      • 需要 &mut SliceInner:Default
  • std::操作::*
    • Derefimplstd::ops::Deref forSlice{type Target = SliceInner;/* .. */}
    • DerefMut: impl std::ops::DerefMut for Slice { /* .. */ }
      • 需要 Deref<Target = SliceInner> for Slice

许可证

根据您的选择,许可协议为以下之一:

贡献

除非您明确声明,否则根据 Apache-2.0 许可证定义的,您有意提交并包含在作品中的任何贡献,都将按上述方式双许可,不附加任何额外的条款或条件。

依赖

~2MB
~46K SLoC