Nutype는 정기적 인 NewType 패턴에 소독 및 검증 과 같은 추가 제약 조건을 추가 할 수있는 Proc 매크로입니다. 생성 된 코드는 수표를 전달하지 않고 값을 인스턴스화하는 것이 불가능합니다. serde Deserialization에서도 이런 식으로 작동합니다.
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 , 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로 형식을 확인합니다. regex 기능이 필요합니다. | RegexViolated | regex = "^[0-9]{7}$" 또는 regex = ID_REGEX |
predicate | 맞춤 유효성 검사기. &str 및 racks bool 받는 기능 또는 폐쇄 | PredicateViolated | predicate = |s: &str| s.contains('@') |
with | 사용자 정의 오류가있는 사용자 정의 유효성 검사기 | N/A | (아래 예제 참조) |
요구 사항 :
nutype 의 regex 기능이 활성화되었습니다.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 , FromStr , AsRef , Deref , From , TryFrom Into , Hash , Borrow , Display , Default , Serialize , Deserialize .
정수 내부 유형은 u8 , u16 , u32 , u64 , u128 , i8 , i16 , i32 , 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 Debug , Clone , Copy , PartialEq , Eq , PartialOrd , Ord , FromStr , AsRef , Deref , Into , From , Borrow , Display Default Hash 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 Borrow Clone , Copy , PartialEq , Eq , PartialOrd , Ord , FromStr , AsRef , Deref , Into , From , TryFrom , Borring, Display , Default , Serialize , Deref, Deref는 플로트 기반 유형에 대해 다음과 같은 특성을 도출 할 Hash Deserialize .
유효성 검사 규칙에 NaN 제외되도록 보장하는 경우 Eq 및 Ord 도출 할 수도 있습니다. finite 검증으로 적용 할 수 있습니다. 예를 들어:
# [ nutype (
validate ( finite ) ,
derive ( PartialEq , Eq , PartialOrd , Ord ) ,
) ]
struct Size ( f64 ) ; 다른 유형의 경우 predicate with 하여 사용자 정의 소독제를 정의 할 수 있습니다.
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 옵션을 사용하여 사용자 정의 소독제를 설정할 수 있습니다. 사용자 정의 소독제는 소유권이있는 내부 유형의 값을 수신하고 소독 값을 반환하는 함수 또는 폐쇄입니다.
예를 들어, 이것은이 것입니다
# [ 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 and 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 안전하지 않은 생성 ::new_unchecked() 함수를 활성화합니다.regex 문자열 기반 유형에서 regex = 검증을 사용할 수 있습니다. 참고 : 상자는 또한 종속성 내에서 명시 적으로 regex 늘어야합니다.serde serde Crate와의 통합. Serialize 및 특성을 Deserialize 시킬 수 있습니다.schemars08 스키마 상자의 JsonSchema 특성을 도출 할 수 있습니다. 현재 유효성 검사 규칙은 존중되지 않습니다.std 기본적으로 활성화. 비활성화하려면 default-features = false 사용하십시오. 오늘 저는 베를린에 살고 있습니다. 나는 육체적으로 안전한 삶을 살기 위해 사치를 가지고 있습니다. 그러나 나는 우크라이나입니다. 내가 러시아와의 국경에서 60km 떨어진 우크라이나에서 두 번째로 큰 도시인 카르 키프 (Kharkiv)에서 보낸 내 인생의 처음 25 년. 오늘날 내 고향의 3 분의 1은 러시아인들에 의해 파괴되었습니다. 부모님, 친척 및 친구들은 지하실에서 한 달 이상 살고있는 포병과 공중 공격에서 살아남아야했습니다.
그들 중 일부는 EU로 대피했습니다. 어떤 사람들은 카르 키프에서 "정상적인 삶"을 살려고 노력하고 있으며 매일 의무를 다하고 있습니다. 그리고 일부는 현재 최전선에 있으며 나머지를 보호하기 위해 매 순간마다 목숨을 걸고 있습니다.
Serhiy Prytula의 자선 재단에 기부하는 것이 좋습니다. 좋아하는 프로젝트를 선택하고 기부하십시오. 이것은 가장 유명한 기초 중 하나이며, 그것에 대한 약간의 다큐멘터리를 볼 수 있습니다. 우크라이나 군사에 대한 당신의 기여는 나의 평온에 기여하기 때문에 프로젝트를 개발하는 데 더 많은 시간을 할애 할 수 있습니다.
감사합니다.
MIT © Serhii Potapov