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 ) ;可以針對基於字符串的類型得出以下特徵:調試, Clone , PartialEq , Eq , PartialOrd , Ord off, FromStr ,str,asref, AsRef , Deref ,trof Debug , 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。 | (請參閱下面的示例) |
可以針對基於整數的類型得出以下特徵: TryFrom ,克隆, Copy , PartialEq , Eq ,eq, PartialOrd , Ord , Clone , FromStr , AsRef , Deref , Into ,to, From Debug ,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。 | (請參閱下面的示例) |
可以為基於浮點的類型得出以下特徵: TryFrom ,克隆, Copy , PartialEq , Eq ,eq, PartialOrd , Ord ,ods Clone , FromStr , AsRef , Deref , Into ,to, From Debug ,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