Crates.io | property |
lib.rs | property |
version | 0.4.0-alpha.0 |
source | src |
created_at | 2019-04-26 00:27:30.831811 |
updated_at | 2021-05-09 17:36:54.686546 |
description | Generate several common methods for structs automatically. |
homepage | https://github.com/yangby-cryptape/rust-property |
repository | https://github.com/yangby-cryptape/rust-property |
max_upload_size | |
id | 130229 |
size | 72,558 |
Generate several common methods for structs automatically.
Apply the derive proc-macro #[derive(Property)]
to structs, and use #[property(..)]
to configure it.
There are three levels of properties:
Set crate properties can change the default settings for all containers (structs) in the whole crate.
Limited by the procedural macros, here we have to use a tricky way to set the crate properties:
#[property_default(get(..), set(..), ..)]
struct PropertyCrateConf; // This struct is only used for introducing the attribute macro, and it will be removed in the macro.
Set container properties can change the default properties for all fields in the container.
Change the settings of a single field via setting field properties.
If no properties is set, the default properties will be applied:
#[property(
get(crate, prefix = "", suffix = "", type="auto"),
set(crate, prefix = "set_", type = "ref"),
mut(crate, prefix = "mut_"),
clr(crate, prefix = "clear_", scope = "option")
ord(asc)
)]
There are six kinds of configurable properties: skip
, get
, set
, mut
, clr
and ord
.
If the skip
property is set, no methods will be generated.
The visibility of a method can be set via #[property(get(visibility-type))]
There are four kinds of the visibility types: disable
, public
, crate
(default for all methods), and private
.
The method name can be set in two ways:
Assign a complete name via #[property(get(name = "method-name"))]
.
Set prefix
and / or suffix
via #[property(set(prefix = "set_"), mut(suffix = "mut_"))]
.
The default setting for all fields is: #[property(get(prefix = "", suffix = ""), set(prefix = "set_"), mut(prefix = "mut_"))]
.
The return type of get
method can be set via #[property(get(type = "return-type"))]
.
There are four kinds of the return types: auto
(default), ref
, clone
and copy
.
The input type and return type of set
method can be set via #[property(set(type = "set-type"))]
.
There are four kinds of the input types: ref
(default), own
, none
and replace
:
ref
: input is a mutable reference and return is the mutable reference too.
own
: input is a owned object and return is the owned object too.
none
: input is a mutable reference and no return.
replace
: input is a mutable reference and return the old value.
There is an extra property for set
method:
full_option
: if the value is Option<T>
, then the default argument is T
without this property.The clr
method will set a field to its default value. It has a scope
property:
auto
: will generate clr
method for some preset types, such as Vec
, Option
, and so on.
option
: (default) will generate clr
method for Option
only.
all
: will generate clr
method for all types.
If there are more than one filed have the ord
property, the PartialEq
and PartialOrd
will be implemented automatically.
A serial number is required for the ord
field property, it's an unsigned number with a _
prefix.
The serial numbers could be noncontinuous, but any two number of these could not be equal.
No serial number is allowed if the ord
property is a container property.
There are two kind of sort types: asc
and desc
.
The default is ascending (asc
), it can be changed to descending if the desc
was set.
#![no_std]
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std as alloc;
use alloc::{string::String, vec::Vec};
use property::{property_default, Property};
#[property_default(get(public), ord(desc), clr(scope = "option"))]
struct PropertyCrateConf;
#[derive(Copy, Clone)]
pub enum Species {
Dog,
Cat,
Bird,
Other,
}
#[derive(Property)]
#[property(set(private), mut(disable))]
pub struct Pet {
#[property(get(name = "identification"), set(disable), ord(asc, _2))]
id: [u8; 32],
name: String,
#[property(set(crate, type = "own"), ord(_0))]
age: u32,
#[property(get(type = "copy"))]
species: Species,
#[property(get(prefix = "is_"), ord(_1))]
died: bool,
#[property(get(type = "clone"), set(type = "none"))]
owner: String,
#[property(clr(scope = "auto"))]
family_members: Vec<String>,
#[property(get(type = "ref"), mut(crate))]
info: String,
#[property(get(disable), set(type = "replace"))]
pub tag: Vec<String>,
#[property(mut(public, suffix = "_mut"))]
note: Option<String>,
#[property(set(type = "replace", full_option))]
price: Option<u32>,
#[property(skip)]
pub reserved: String,
}
impl Pet {
#[inline]
pub fn identification(&self) -> &[u8] {
&self.id[..]
}
#[inline]
pub fn name(&self) -> &str {
&self.name[..]
}
#[inline]
fn set_name<T: Into<String>>(&mut self, val: T) -> &mut Self {
self.name = val.into();
self
}
#[inline]
pub fn age(&self) -> u32 {
self.age
}
#[inline]
pub(crate) fn set_age<T: Into<u32>>(mut self, val: T) -> Self {
self.age = val.into();
self
}
#[inline]
pub fn species(&self) -> Species {
self.species
}
#[inline]
fn set_species<T: Into<Species>>(&mut self, val: T) -> &mut Self {
self.species = val.into();
self
}
#[inline]
pub fn is_died(&self) -> bool {
self.died
}
#[inline]
fn set_died<T: Into<bool>>(&mut self, val: T) -> &mut Self {
self.died = val.into();
self
}
#[inline]
pub fn owner(&self) -> String {
self.owner.clone()
}
#[inline]
fn set_owner<T: Into<String>>(&mut self, val: T) {
self.owner = val.into();
}
#[inline]
pub fn family_members(&self) -> &[String] {
&self.family_members[..]
}
#[inline]
fn set_family_members<T: Into<String>>(
&mut self,
val: impl IntoIterator<Item = T>,
) -> &mut Self {
self.family_members = val.into_iter().map(Into::into).collect();
self
}
#[inline]
pub(crate) fn clear_family_members(&mut self) {
self.family_members.clear();
}
#[inline]
pub fn info(&self) -> &String {
&self.info
}
#[inline]
fn set_info<T: Into<String>>(&mut self, val: T) -> &mut Self {
self.info = val.into();
self
}
#[inline]
pub(crate) fn mut_info(&mut self) -> &mut String {
&mut self.info
}
#[inline]
fn set_tag<T: Into<String>>(&mut self, val: impl IntoIterator<Item = T>) -> Vec<String> {
::core::mem::replace(&mut self.tag, val.into_iter().map(Into::into).collect())
}
#[inline]
pub fn note(&self) -> Option<&String> {
self.note.as_ref()
}
#[inline]
fn set_note<T: Into<String>>(&mut self, val: T) -> &mut Self {
self.note = Some(val.into());
self
}
#[inline]
pub fn note_mut(&mut self) -> &mut Option<String> {
&mut self.note
}
#[inline]
pub(crate) fn clear_note(&mut self) {
self.note = None;
}
#[inline]
pub fn price(&self) -> Option<u32> {
self.price
}
#[inline]
fn set_price<T: Into<Option<u32>>>(&mut self, val: T) -> Option<u32> {
::core::mem::replace(&mut self.price, val.into())
}
#[inline]
pub(crate) fn clear_price(&mut self) {
self.price = None;
}
}
impl PartialEq for Pet {
fn eq(&self, other: &Self) -> bool {
self.age == other.age && self.died == other.died && self.id == other.id
}
}
impl PartialOrd for Pet {
fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
let result = other.age.partial_cmp(&self.age);
if result != Some(::core::cmp::Ordering::Equal) {
return result;
}
let result = other.died.partial_cmp(&self.died);
if result != Some(::core::cmp::Ordering::Equal) {
return result;
}
let result = self.id.partial_cmp(&other.id);
if result != Some(::core::cmp::Ordering::Equal) {
return result;
}
Some(::core::cmp::Ordering::Equal)
}
}
Enjoy it!
Licensed under either of Apache License, Version 2.0 or MIT License, at your option.