Nutype是一个PROC宏,允许在常规的NewType模式中添加诸如消毒和验证之类的额外约束。生成的代码使得无需传递检查就无法实例化值。即使在serde避难所化的情况下,它也可以使用。
use nutype :: nutype ;
// Define newtype Username
# [ nutype (
sanitize ( trim , lowercase ) ,
validate ( not_empty , len_char_max = 20 ) ,
derive ( Debug , PartialEq , Clone ) ,
) ]
pub struct Username ( String ) ;
// We can obtain a value of Username with `::try_new()`.
// Note that Username holds a sanitized string
assert_eq ! (
Username :: try_new ( " FooBar " ) . unwrap ( ) . into_inner ( ) ,
"foobar"
) ;
// It's impossible to obtain an invalid Username
// Note that we also got `UsernameError` enum generated implicitly
// based on the validation rules.
assert_eq ! (
Username :: try_new ( " " ) ,
Err ( UsernameError :: NotEmptyViolated ) ,
) ;
assert_eq ! (
Username :: try_new ( "TheUserNameIsVeryVeryLong" ) ,
Err ( UsernameError :: LenCharMaxViolated ) ,
) ;有关更多信息,请参阅:
可用的消毒剂,验证器和可衍生性状由内部类型确定,该类型属于以下类别:
u8 , u16 , u32 , u64 , u128 , i8 , i16 , i32 , i64 ,I64, i128 , usize , isize )f32 , f64 )目前,字符串内类型仅支持String (拥有)类型。
| 消毒剂 | 描述 | 例子 |
|---|---|---|
trim | 去除领先和落后的空间 | trim |
lowercase | 将字符串转换为小写 | lowercase |
uppercase | 将字符串转换为大写 | uppercase |
with | 定制消毒剂。接收String并返回String的功能或闭合 | with = |mut s: String| ( s.truncate(5); s ) |
| 验证器 | 描述 | 错误变体 | 例子 |
|---|---|---|---|
len_char_min | 字符串的最小长度(以字符而不是字节) | LenCharMinViolated | len_char_min = 5 |
len_char_max | 字符串的最大长度(以字符而不是字节) | LenCharMaxViolated | len_char_max = 255 |
not_empty | 拒绝一个空字符串 | NotEmptyViolated | not_empty |
regex | 用正则验证格式。需要regex功能。 | RegexViolated | regex = "^[0-9]{7}$"或regex = ID_REGEX |
predicate | 自定义验证器。接收&str并返回bool的功能或闭合 | PredicateViolated | predicate = |s: &str| s.contains('@') |
with | 具有自定义错误的自定义验证器 | N/A。 | (请参阅下面的示例) |
要求:
nutype的regex功能。regex作为依赖性。您可以通过多种方式使用正则言语。
正则表达式可以正确定义:
# [ nutype ( validate ( regex = "^[0-9]{3}-[0-9]{3}$" ) ) ]
pub struct PhoneNumber ( String ) ;否则可以用std::sync::LazyLock定义它:
use regex :: Regex ;
static PHONE_NUMBER_REGEX : LazyLock < Regex > = LazyLock :: new ( || Regex :: new ( "^[0-9]{3}-[0-9]{3}$" ) . unwrap ( ) ) ;
# [ nutype ( validate ( regex = PHONE_NUMBER_REGEX ) ) ]
pub struct PhoneNumber ( String ) ;否则可以用lazy_static来定义:
use lazy_static :: lazy_static ;
use regex :: Regex ;
lazy_static ! {
static ref PHONE_NUMBER_REGEX : Regex = Regex :: new ( "^[0-9]{3}-[0-9]{3}$" ) . unwrap ( ) ;
}
# [ nutype ( validate ( regex = PHONE_NUMBER_REGEX ) ) ]
pub struct PhoneNumber ( String ) ;或once_cell :
use once_cell :: sync :: Lazy ;
use regex :: Regex ;
static PHONE_NUMBER_REGEX : Lazy < Regex > =
Lazy :: new ( || Regex :: new ( "[0-9]{3}-[0-9]{3}$" ) . unwrap ( ) ) ;
# [ nutype ( validate ( regex = PHONE_NUMBER_REGEX ) ) ]
pub struct PhoneNumber ( String ) ;可以针对基于字符串的类型得出以下特征: Debug , Clone , PartialEq , Eq , PartialOrd , Ord off, FromStr ,str,asref, AsRef , Deref ,trof tryfrom, From ,to to,to, Hash , TryFrom ,borrow,borrow, Into , Borrow , Display , Default Serialize , Deserialize 。
整数内部类型为: u8 , u16 , u32 , u64 , u128 , i8 , i16 ,I16, i32 ,I64, i64 , i128 , usize , isize 。
| 消毒剂 | 描述 | 例子 |
|---|---|---|
with | 定制消毒剂。 | with = |raw| raw.clamp(0, 100) |
| 验证器 | 描述 | 错误变体 | 例子 |
|---|---|---|---|
less | 独家上限 | LessViolated | less = 100 |
less_or_equal | 包容性上限 | LessOrEqualViolated | less_or_equal = 99 |
greater | 独家下限 | GreaterViolated | greater = 17 |
greater_or_equal | 包容性下限 | GreaterOrEqualViolated | greater_or_equal = 18 |
predicate | 自定义谓词 | PredicateViolated | predicate = |num| num % 2 == 0 |
with | 具有自定义错误的自定义验证器 | N/A。 | (请参阅下面的示例) |
可以针对基于整数的类型得出以下特征: Debug , Clone , Copy , PartialEq , Eq ,eq, PartialOrd , Ord , FromStr ,asref, AsRef , Deref , Into ,to, From TryFrom ,tryfrom,hash, Borrow ,borrow,borrow, Hash , Display , Default ,serialialize,serialize Serialize Deserialize 。
浮子内部类型为: f32 , f64 。
| 消毒剂 | 描述 | 例子 |
|---|---|---|
with | 定制消毒剂。 | with = |val| val.clamp(0.0, 100.0) |
| 验证器 | 描述 | 错误变体 | 例子 |
|---|---|---|---|
less | 独家上限 | LessViolated | less = 100.0 |
less_or_equal | 包容性上限 | LessOrEqualViolated | less_or_equal = 100.0 |
greater | 独家下限 | GreaterViolated | greater = 0.0 |
greater_or_equal | 包容性下限 | GreaterOrEqualViolated | greater_or_equal = 0.0 |
finite | 对Nan和Infinity进行检查 | FiniteViolated | finite |
predicate | 自定义谓词 | PredicateViolated | predicate = |val| val != 50.0 |
with | 具有自定义错误的自定义验证器 | N/A。 | (请参阅下面的示例) |
可以为基于浮点的类型得出以下特征: Debug , Clone , Copy , PartialEq , Eq ,eq, PartialOrd , Ord ,ods ofstr, FromStr , AsRef , Deref , Into ,to, From TryFrom ,tryfrom,hash,borrow,borrow,display, Hash , Default , Borrow , Display Serialize , Deserialize 。
如果验证规则保证NaN被排除在外,也可以得出Eq和Ord 。这可以通过finite验证进行应用。例如:
# [ nutype (
validate ( finite ) ,
derive ( PartialEq , Eq , PartialOrd , Ord ) ,
) ]
struct Size ( f64 ) ; 对于任何其他类型,都可以使用with predicate的自定义验证定义自定义消毒器:
use nutype :: nutype ;
# [ nutype (
derive ( Debug , PartialEq , AsRef , Deref ) ,
sanitize ( with = | mut guests| { guests . sort ( ) ; guests } ) ,
validate ( predicate = |guests| !guests . is_empty ( ) ) ,
) ]
pub struct GuestList ( Vec < String > ) ;也可以使用仿制药:
# [ nutype (
sanitize ( with = | mut v| { v . sort ( ) ; v } ) ,
validate ( predicate = |vec| !vec . is_empty ( ) ) ,
derive ( Debug , PartialEq , AsRef , Deref ) ,
) ]
struct SortedNotEmptyVec < T : Ord > ( Vec < T > ) ;
let wise_friends = SortedNotEmptyVec :: try_new ( vec ! [ "Seneca" , "Zeno" , "Plato" ] ) . unwrap ( ) ;
assert_eq ! ( wise_friends . as_ref ( ) , & [ "Plato" , "Seneca" , "Zeno" ] ) ;
assert_eq ! ( wise_friends . len ( ) , 3 ) ;
let numbers = SortedNotEmptyVec :: try_new ( vec ! [ 4 , 2 , 7 , 1 ] ) . unwrap ( ) ;
assert_eq ! ( numbers . as_ref ( ) , & [ 1 , 2 , 4 , 7 ] ) ;
assert_eq ! ( numbers . len ( ) , 4 ) ; 您可以使用with OPTION设置自定义消毒器。自定义消毒剂是一个函数或闭合,可接收具有所有权的内部类型的值并返回消毒值。
例如,这个
# [ nutype ( sanitize ( with = new_to_old ) ) ]
pub struct CityName ( String ) ;
fn new_to_old ( s : String ) -> String {
s . replace ( "New" , "Old" )
}等于以下一个:
# [ nutype ( sanitize ( with = |s| s . replace ( "New" , "Old" ) ) ) ]
pub struct CityName ( String ) ;并以同样的方式工作:
let city = CityName :: new ( "New York" ) ;
assert_eq ! ( city . into_inner ( ) , "Old York" ) ; 以类似的方式可以定义自定义验证器,但是验证功能会收到参考并返回bool 。将其视为谓词。
# [ nutype ( validate ( predicate = is_valid_name ) ) ]
pub struct Name ( String ) ;
fn is_valid_name ( name : & str ) -> bool {
// A fancy way to verify if the first character is uppercase
name . chars ( ) . next ( ) . map ( char :: is_uppercase ) . unwrap_or ( false )
} 为了定义您自己的错误类型并实现自定义验证逻辑,您可以将这些with与error属性结合在一起:
// Define a custom error type for validation failures.
// Although it's best practice to implement `std::error::Error` for custom error types,
// we are omitting that for simplicity here.
# [ derive ( Debug , PartialEq ) ]
enum NameError {
TooShort ,
TooLong ,
}
// Define a custom validation function for `Name`.
// The function returns `Result<(), NameError>`, where `Ok(())` indicates a valid name,
// and `Err(NameError)` represents a specific validation failure.
fn validate_name ( name : & str ) -> Result < ( ) , NameError > {
if name . len ( ) < 3 {
Err ( NameError :: TooShort )
} else if name . len ( ) > 10 {
Err ( NameError :: TooLong )
} else {
Ok ( ( ) )
}
}
// Define a newtype `Name` with custom validation logic and custom error.
# [ nutype (
validate ( with = validate_name , error = NameError ) ,
derive ( Debug , PartialEq ) ,
) ]
struct Name ( String ) ;重要的是要确保error属性中指定的类型与验证函数返回的错误类型匹配。
Default # [ nutype (
derive ( Default ) ,
default = "Anonymous" ,
) ]
pub struct Name ( String ) ;Eq和Ord使用Nutype,如果有finite验证集,则可以得出Eq和Ord 。 finite验证可确保有效值不包括NaN 。
# [ nutype (
validate ( finite ) ,
derive ( PartialEq , Eq , PartialOrd , Ord ) ,
) ]
pub struct Weight ( f64 ) ; 它劝阻了,但是可以通过启用new_unchecked板条板功能并用new_unchecked标记类型来绕过约束:
# [ nutype (
new_unchecked ,
sanitize ( trim ) ,
validate ( len_char_min = 8 )
) ]
pub struct Name ( String ) ;
// Yes, you're forced to use `unsafe` here, so everyone will point fingers at YOU.
let name = unsafe { Name :: new_unchecked ( " boo " . to_string ( ) ) } ;
// `name` violates the sanitization and validation rules!!!
assert_eq ! ( name . into_inner ( ) , " boo " ) ; arbitrary - 启用arbitrary::Arbitrary 。new_unchecked启用Unsafe ::new_unchecked()函数的生成。regex允许在基于字符串的类型上使用regex =验证。注意:您的板条箱还必须在其依赖项中明确具有regex 。serde与serde Crate集成。允许得出Serialize和Deserialize性状。schemars08允许得出jsonschema板条箱的JsonSchema特征。请注意,目前验证规则尚未尊重。std默认启用。使用default-features = false禁用。 今天,我住在柏林,我有奢侈的生活在身体上安全的生活。但是我是乌克兰人。我一生的前25年在哈尔基夫(Kharkiv)度过,乌克兰第二大城市距离与俄罗斯边境60公里。今天,大约三分之一的家乡被俄罗斯人摧毁。我的父母,我的亲戚和朋友必须在地下室生活一个多月。
他们中的一些人设法撤离了欧盟。其他一些人则试图在哈尔基夫(Kharkiv)过上“正常的生活”,每天都在那里履行职责。现在有些处于前线,每秒冒着生命危险以保护其余的人。
我鼓励您捐赠给Serhiy Prytula的慈善基金会。只需选择您喜欢的项目并捐赠即可。这是最著名的基础之一,您可以观看有关它的一些纪录片。您对乌克兰军事力量的贡献是对我平静的贡献,因此我可以花更多的时间开发该项目。
谢谢。
MIT©Serhii Potapov