• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gengteng / axum-valid / 6594566229

21 Oct 2023 01:57AM UTC coverage: 89.579% (+2.9%) from 86.699%
6594566229

push

github

gengteng
add tests for validify extractors

124 of 124 new or added lines in 1 file covered. (100.0%)

1427 of 1593 relevant lines covered (89.58%)

12.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.83
/src/validify/test.rs
1
#![cfg(feature = "validify")]
2

3
use crate::tests::{ValidTest, ValidTestParameter};
4
use crate::{
5
    HasValidate, Modified, Validated, Validified, ValidifiedByRef, VALIDATION_ERROR_STATUS,
6
};
7
use axum::extract::{Path, Query};
8
use axum::routing::{get, post};
9
use axum::{Form, Json, Router};
10
use hyper::Method;
11
use once_cell::sync::Lazy;
12
use reqwest::{StatusCode, Url};
13
use serde::{Deserialize, Serialize};
14
use std::any::type_name;
15
use std::net::SocketAddr;
16
use std::ops::Deref;
17
use validify::{Modify, Validate, Validify};
18

19
#[derive(Clone, Deserialize, Serialize, Validify, Eq, PartialEq)]
20
#[cfg_attr(feature = "extra_protobuf", derive(prost::Message))]
21
#[cfg_attr(
22
    feature = "typed_multipart",
23
    derive(axum_typed_multipart::TryFromMultipart)
24
)]
25
pub struct ParametersValidify {
26
    #[validate(range(min = 5.0, max = 10.0))]
27
    #[cfg_attr(feature = "extra_protobuf", prost(int32, tag = "1"))]
28
    v0: i32,
29
    #[modify(lowercase)]
30
    #[validate(length(min = 1, max = 10))]
31
    #[cfg_attr(feature = "extra_protobuf", prost(string, tag = "2"))]
32
    v1: String,
33
}
34

35
trait IsModified: Modify + Clone + PartialEq + Eq {
36
    fn modified(&self) -> bool {
9✔
37
        let mut cloned = self.clone();
9✔
38
        cloned.modify();
9✔
39
        cloned == *self
9✔
40
    }
41
}
42

43
impl<T> IsModified for T where T: Modify + Clone + PartialEq + Eq {}
44

45
static VALID_PARAMETERS: Lazy<ParametersValidify> = Lazy::new(|| ParametersValidify {
6✔
46
    v0: 5,
47
    v1: String::from("ABCDEFG"),
3✔
48
});
49

50
static INVALID_PARAMETERS: Lazy<ParametersValidify> = Lazy::new(|| ParametersValidify {
6✔
51
    v0: 6,
52
    v1: String::from("ABCDEFGHIJKLMN"),
3✔
53
});
54

55
impl ValidTestParameter for ParametersValidify {
56
    fn valid() -> &'static Self {
3✔
57
        VALID_PARAMETERS.deref()
3✔
58
    }
59

60
    fn error() -> &'static [(&'static str, &'static str)] {
61
        &[("not_v0_or_v1", "value")]
62
    }
63

64
    fn invalid() -> &'static Self {
3✔
65
        INVALID_PARAMETERS.deref()
3✔
66
    }
67
}
68

69
impl HasValidate for ParametersValidify {
70
    type Validate = ParametersValidify;
71

72
    fn get_validate(&self) -> &Self::Validate {
3✔
73
        self
74
    }
75
}
76

77
#[tokio::test]
18✔
78
async fn test_main() -> anyhow::Result<()> {
9✔
79
    let router = Router::new()
51✔
80
        .route(route::PATH, get(extract_path))
6✔
81
        .route(route::PATH_MODIFIED, get(extract_path_modified))
6✔
82
        .route(route::PATH_VALIDIFIED, get(extract_path_validified))
6✔
83
        .route(
84
            route::PATH_VALIDIFIED_BY_REF,
85
            get(extract_path_validified_by_ref),
3✔
86
        )
87
        .route(route::QUERY, get(extract_query))
6✔
88
        .route(route::QUERY_MODIFIED, get(extract_query_modified))
6✔
89
        .route(route::QUERY_VALIDIFIED, get(extract_query_validified))
6✔
90
        .route(
91
            route::QUERY_VALIDIFIED_BY_REF,
92
            get(extract_query_validified_by_ref),
3✔
93
        )
94
        .route(route::FORM, post(extract_form))
6✔
95
        .route(route::FORM_MODIFIED, post(extract_form_modified))
6✔
96
        .route(route::FORM_VALIDIFIED, post(extract_form_validified))
6✔
97
        .route(
98
            route::FORM_VALIDIFIED_BY_REF,
99
            post(extract_form_validified_by_ref),
3✔
100
        )
101
        .route(route::JSON, post(extract_json))
6✔
102
        .route(route::JSON_MODIFIED, post(extract_json_modified))
6✔
103
        .route(route::JSON_VALIDIFIED, post(extract_json_validified))
6✔
104
        .route(
105
            route::JSON_VALIDIFIED_BY_REF,
106
            post(extract_json_validified_by_ref),
3✔
107
        );
108

109
    #[cfg(feature = "typed_header")]
110
    let router = router
12✔
111
        .route(
112
            typed_header::route::TYPED_HEADER,
113
            post(typed_header::extract_typed_header),
3✔
114
        )
115
        .route(
116
            typed_header::route::TYPED_HEADER_MODIFIED,
117
            post(typed_header::extract_typed_header_modified),
3✔
118
        )
119
        .route(
120
            typed_header::route::TYPED_HEADER_VALIDIFIED_BY_REF,
121
            post(typed_header::extract_typed_header_validified_by_ref),
3✔
122
        );
123

124
    #[cfg(feature = "typed_multipart")]
125
    let router = router
21✔
126
        .route(
127
            typed_multipart::route::TYPED_MULTIPART,
128
            post(typed_multipart::extract_typed_multipart),
3✔
129
        )
130
        .route(
131
            typed_multipart::route::TYPED_MULTIPART_MODIFIED,
132
            post(typed_multipart::extract_typed_multipart_modified),
3✔
133
        )
134
        .route(
135
            typed_multipart::route::TYPED_MULTIPART_VALIDIFIED_BY_REF,
136
            post(typed_multipart::extract_typed_multipart_validified_by_ref),
3✔
137
        )
138
        .route(
139
            typed_multipart::route::BASE_MULTIPART,
140
            post(typed_multipart::extract_base_multipart),
3✔
141
        )
142
        .route(
143
            typed_multipart::route::BASE_MULTIPART_MODIFIED,
144
            post(typed_multipart::extract_base_multipart_modified),
3✔
145
        )
146
        .route(
147
            typed_multipart::route::BASE_MULTIPART_VALIDIFIED_BY_REF,
148
            post(typed_multipart::extract_base_multipart_validified_by_ref),
3✔
149
        );
150

151
    #[cfg(feature = "extra")]
152
    let router = router
24✔
153
        .route(extra::route::CACHED, post(extra::extract_cached))
6✔
154
        .route(
155
            extra::route::CACHED_MODIFIED,
156
            post(extra::extract_cached_modified),
3✔
157
        )
158
        .route(
159
            extra::route::CACHED_VALIDIFIED_BY_REF,
160
            post(extra::extract_cached_validified_by_ref),
3✔
161
        )
162
        .route(
163
            extra::route::WITH_REJECTION,
164
            post(extra::extract_with_rejection),
3✔
165
        )
166
        .route(
167
            extra::route::WITH_REJECTION_MODIFIED,
168
            post(extra::extract_with_rejection_modified),
3✔
169
        )
170
        .route(
171
            extra::route::WITH_REJECTION_VALIDIFIED_BY_REF,
172
            post(extra::extract_with_rejection_validified_by_ref),
3✔
173
        )
174
        .route(
175
            extra::route::WITH_REJECTION_VALIDIFY,
176
            post(extra::extract_with_rejection_valid),
3✔
177
        );
178

179
    #[cfg(feature = "extra_typed_path")]
180
    let router = router
12✔
181
        .route(
182
            extra_typed_path::route::EXTRA_TYPED_PATH,
183
            get(extra_typed_path::extract_extra_typed_path),
3✔
184
        )
185
        .route(
186
            extra_typed_path::route::EXTRA_TYPED_PATH_MODIFIED,
187
            get(extra_typed_path::extract_extra_typed_path_modified),
3✔
188
        )
189
        .route(
190
            extra_typed_path::route::EXTRA_TYPED_PATH_VALIDIFIED_BY_REF,
191
            get(extra_typed_path::extract_extra_typed_path_validified_by_ref),
3✔
192
        );
193

194
    #[cfg(feature = "extra_query")]
195
    let router = router
15✔
196
        .route(
197
            extra_query::route::EXTRA_QUERY,
198
            post(extra_query::extract_extra_query),
3✔
199
        )
200
        .route(
201
            extra_query::route::EXTRA_QUERY_MODIFIED,
202
            post(extra_query::extract_extra_query_modified),
3✔
203
        )
204
        .route(
205
            extra_query::route::EXTRA_QUERY_VALIDIFIED,
206
            post(extra_query::extract_extra_query_validified),
3✔
207
        )
208
        .route(
209
            extra_query::route::EXTRA_QUERY_VALIDIFIED_BY_REF,
210
            post(extra_query::extract_extra_query_validified_by_ref),
3✔
211
        );
212

213
    #[cfg(feature = "extra_form")]
214
    let router = router
15✔
215
        .route(
216
            extra_form::route::EXTRA_FORM,
217
            post(extra_form::extract_extra_form),
3✔
218
        )
219
        .route(
220
            extra_form::route::EXTRA_FORM_MODIFIED,
221
            post(extra_form::extract_extra_form_modified),
3✔
222
        )
223
        .route(
224
            extra_form::route::EXTRA_FORM_VALIDIFED,
225
            post(extra_form::extract_extra_form_validifed),
3✔
226
        )
227
        .route(
228
            extra_form::route::EXTRA_FORM_VALIDIFED_BY_REF,
229
            post(extra_form::extract_extra_form_validifed_by_ref),
3✔
230
        );
231

232
    #[cfg(feature = "extra_protobuf")]
233
    let router = router
12✔
234
        .route(
235
            extra_protobuf::route::EXTRA_PROTOBUF,
236
            post(extra_protobuf::extract_extra_protobuf),
3✔
237
        )
238
        .route(
239
            extra_protobuf::route::EXTRA_PROTOBUF_MODIFIED,
240
            post(extra_protobuf::extract_extra_protobuf_modified),
3✔
241
        )
242
        .route(
243
            extra_protobuf::route::EXTRA_PROTOBUF_VALIDIFIED_BY_REF,
244
            post(extra_protobuf::extract_extra_protobuf_validified_by_ref),
3✔
245
        );
246

247
    #[cfg(feature = "yaml")]
248
    let router = router
15✔
249
        .route(yaml::route::YAML, post(yaml::extract_yaml))
6✔
250
        .route(
251
            yaml::route::YAML_MODIFIED,
252
            post(yaml::extract_yaml_modified),
3✔
253
        )
254
        .route(
255
            yaml::route::YAML_VALIDIFIED,
256
            post(yaml::extract_yaml_validified),
3✔
257
        )
258
        .route(
259
            yaml::route::YAML_VALIDIFIED_BY_REF,
260
            post(yaml::extract_yaml_validified_by_ref),
3✔
261
        );
262

263
    #[cfg(feature = "msgpack")]
264
    let router = router
27✔
265
        .route(msgpack::route::MSGPACK, post(msgpack::extract_msgpack))
6✔
266
        .route(
267
            msgpack::route::MSGPACK_MODIFIED,
268
            post(msgpack::extract_msgpack_modified),
3✔
269
        )
270
        .route(
271
            msgpack::route::MSGPACK_VALIDIFIED,
272
            post(msgpack::extract_msgpack_validified),
3✔
273
        )
274
        .route(
275
            msgpack::route::MSGPACK_VALIDIFIED_BY_REF,
276
            post(msgpack::extract_msgpack_validified_by_ref),
3✔
277
        )
278
        .route(
279
            msgpack::route::MSGPACK_RAW,
280
            post(msgpack::extract_msgpack_raw),
3✔
281
        )
282
        .route(
283
            msgpack::route::MSGPACK_RAW_MODIFIED,
284
            post(msgpack::extract_msgpack_raw_modified),
3✔
285
        )
286
        .route(
287
            msgpack::route::MSGPACK_RAW_VALIDIFIED,
288
            post(msgpack::extract_msgpack_raw_validified),
3✔
289
        )
290
        .route(
291
            msgpack::route::MSGPACK_RAW_VALIDIFIED_BY_REF,
292
            post(msgpack::extract_msgpack_raw_validified_by_ref),
3✔
293
        );
294

295
    let server = axum::Server::bind(&SocketAddr::from(([0u8, 0, 0, 0], 0u16)))
9✔
296
        .serve(router.into_make_service());
6✔
297
    let server_addr = server.local_addr();
3✔
298
    println!("Axum server address: {}.", server_addr);
6✔
299

300
    let (server_guard, close) = tokio::sync::oneshot::channel::<()>();
3✔
301
    let server_handle = tokio::spawn(server.with_graceful_shutdown(async move {
15✔
302
        let _ = close.await;
9✔
303
    }));
304

305
    let server_url = format!("http://{}", server_addr);
6✔
306
    let test_executor = TestExecutor::from(Url::parse(&format!("http://{}", server_addr))?);
6✔
307

308
    async fn test_extra_path(
3✔
309
        test_executor: &TestExecutor,
310
        route: &str,
311
        server_url: &str,
312
    ) -> anyhow::Result<()> {
313
        do_test_extra_path(
314
            test_executor,
315
            route,
316
            server_url,
317
            StatusCode::OK,
318
            StatusCode::BAD_REQUEST,
319
            VALIDATION_ERROR_STATUS,
320
            true,
321
        )
322
        .await
9✔
323
    }
324

325
    async fn test_extra_path_modified(
3✔
326
        test_executor: &TestExecutor,
327
        route: &str,
328
        server_url: &str,
329
    ) -> anyhow::Result<()> {
330
        do_test_extra_path(
331
            test_executor,
332
            route,
333
            server_url,
334
            StatusCode::OK,
335
            StatusCode::BAD_REQUEST,
336
            StatusCode::OK,
337
            false,
338
        )
339
        .await
9✔
340
    }
341

342
    async fn test_extra_path_validified(
3✔
343
        test_executor: &TestExecutor,
344
        route: &str,
345
        server_url: &str,
346
    ) -> anyhow::Result<()> {
347
        do_test_extra_path(
348
            test_executor,
349
            route,
350
            server_url,
351
            StatusCode::OK,
352
            StatusCode::BAD_REQUEST,
353
            VALIDATION_ERROR_STATUS,
354
            true,
355
        )
356
        .await
9✔
357
    }
358

359
    async fn do_test_extra_path(
3✔
360
        test_executor: &TestExecutor,
361
        route: &str,
362
        server_url: &str,
363
        expected_valid_status: StatusCode,
364
        expected_error_status: StatusCode,
365
        expected_invalid_status: StatusCode,
366
        should_check_json: bool,
367
    ) -> anyhow::Result<()> {
368
        let path_type_name = type_name::<Path<ParametersValidify>>();
6✔
369
        let valid_path_response = test_executor
12✔
370
            .client()
371
            .get(format!(
21✔
372
                "{}/{route}/{}/{}",
373
                server_url, VALID_PARAMETERS.v0, VALID_PARAMETERS.v1
6✔
374
            ))
375
            .send()
376
            .await?;
9✔
377
        assert_eq!(
3✔
378
            valid_path_response.status(),
6✔
379
            expected_valid_status,
380
            "Valid '{}' test failed.",
381
            path_type_name
382
        );
383

384
        let error_path_response = test_executor
12✔
385
            .client()
386
            .get(format!("{}/{route}/not_i32/path", server_url))
9✔
387
            .send()
388
            .await?;
9✔
389
        assert_eq!(
3✔
390
            error_path_response.status(),
6✔
391
            expected_error_status,
392
            "Error '{}' test failed: {}",
393
            path_type_name,
394
            error_path_response.text().await?
×
395
        );
396

397
        let invalid_path_response = test_executor
12✔
398
            .client()
399
            .get(format!(
21✔
400
                "{}/{route}/{}/{}",
401
                server_url, INVALID_PARAMETERS.v0, INVALID_PARAMETERS.v1
6✔
402
            ))
403
            .send()
404
            .await?;
9✔
405
        assert_eq!(
3✔
406
            invalid_path_response.status(),
6✔
407
            expected_invalid_status,
408
            "Invalid '{}' test failed.",
409
            path_type_name
410
        );
411
        if should_check_json {
2✔
412
            #[cfg(feature = "into_json")]
413
            check_json(path_type_name, invalid_path_response).await;
2✔
414
        }
415
        println!("All {} tests passed.", path_type_name);
6✔
416
        Ok(())
3✔
417
    }
418

419
    test_extra_path(&test_executor, "path", &server_url).await?;
6✔
420
    test_extra_path_modified(&test_executor, "path_modified", &server_url).await?;
9✔
421
    test_extra_path_validified(&test_executor, "path_validified", &server_url).await?;
9✔
422
    test_extra_path(&test_executor, "path_validified_by_ref", &server_url).await?;
9✔
423

424
    // Validated
425
    test_executor
12✔
426
        .execute::<Query<ParametersValidify>>(Method::GET, route::QUERY)
3✔
427
        .await?;
9✔
428
    // Modified
429
    test_executor
12✔
430
        .execute_modified::<Query<ParametersValidify>>(Method::GET, route::QUERY_MODIFIED)
3✔
431
        .await?;
9✔
432
    // ValidifiedByRef
433
    test_executor
12✔
434
        .execute::<Query<ParametersValidify>>(Method::GET, route::QUERY_VALIDIFIED_BY_REF)
3✔
435
        .await?;
9✔
436
    // Validified
437
    test_executor
12✔
438
        .execute_validified::<Query<ParametersValidify>>(Method::GET, route::QUERY_VALIDIFIED)
3✔
439
        .await?;
9✔
440

441
    // Validated
442
    test_executor
12✔
443
        .execute::<Form<ParametersValidify>>(Method::POST, route::FORM)
3✔
444
        .await?;
9✔
445
    // Modified
446
    test_executor
12✔
447
        .execute_modified::<Form<ParametersValidify>>(Method::POST, route::FORM_MODIFIED)
3✔
448
        .await?;
9✔
449
    // ValidifiedByRef
450
    test_executor
12✔
451
        .execute::<Form<ParametersValidify>>(Method::POST, route::FORM_VALIDIFIED_BY_REF)
3✔
452
        .await?;
9✔
453
    // Validified
454
    test_executor
12✔
455
        .execute_validified::<Form<ParametersValidify>>(Method::POST, route::FORM_VALIDIFIED)
3✔
456
        .await?;
9✔
457

458
    // Validated
459
    test_executor
12✔
460
        .execute::<Json<ParametersValidify>>(Method::POST, route::JSON)
3✔
461
        .await?;
9✔
462
    // Modified
463
    test_executor
12✔
464
        .execute_modified::<Json<ParametersValidify>>(Method::POST, route::JSON_MODIFIED)
3✔
465
        .await?;
9✔
466
    // ValidifiedByRef
467
    test_executor
12✔
468
        .execute::<Json<ParametersValidify>>(Method::POST, route::JSON_VALIDIFIED_BY_REF)
3✔
469
        .await?;
9✔
470
    // Validified
471
    test_executor
12✔
472
        .execute_validified::<Json<ParametersValidify>>(Method::POST, route::JSON_VALIDIFIED)
3✔
473
        .await?;
9✔
474

475
    #[cfg(feature = "typed_header")]
476
    {
477
        use axum::TypedHeader;
478
        // Validated
479
        test_executor
12✔
480
            .execute::<TypedHeader<ParametersValidify>>(
481
                Method::POST,
3✔
482
                typed_header::route::TYPED_HEADER,
483
            )
484
            .await?;
9✔
485
        // Modified
486
        test_executor
12✔
487
            .execute_modified::<TypedHeader<ParametersValidify>>(
488
                Method::POST,
3✔
489
                typed_header::route::TYPED_HEADER_MODIFIED,
490
            )
491
            .await?;
9✔
492
        // ValidifiedByRef
493
        test_executor
12✔
494
            .execute::<TypedHeader<ParametersValidify>>(
495
                Method::POST,
3✔
496
                typed_header::route::TYPED_HEADER_VALIDIFIED_BY_REF,
497
            )
498
            .await?;
9✔
499
    }
500

501
    #[cfg(feature = "typed_multipart")]
502
    {
503
        use axum_typed_multipart::{BaseMultipart, TypedMultipart, TypedMultipartError};
504

505
        // Validated
506
        test_executor
12✔
507
            .execute::<BaseMultipart<ParametersValidify, TypedMultipartError>>(
508
                Method::POST,
3✔
509
                typed_multipart::route::BASE_MULTIPART,
510
            )
511
            .await?;
9✔
512
        // Modified
513
        test_executor
12✔
514
            .execute_modified::<BaseMultipart<ParametersValidify, TypedMultipartError>>(
515
                Method::POST,
3✔
516
                typed_multipart::route::BASE_MULTIPART_MODIFIED,
517
            )
518
            .await?;
9✔
519
        // ValidifiedByRef
520
        test_executor
12✔
521
            .execute::<BaseMultipart<ParametersValidify, TypedMultipartError>>(
522
                Method::POST,
3✔
523
                typed_multipart::route::BASE_MULTIPART_VALIDIFIED_BY_REF,
524
            )
525
            .await?;
9✔
526

527
        // Validated
528
        test_executor
12✔
529
            .execute::<TypedMultipart<ParametersValidify>>(
530
                Method::POST,
3✔
531
                typed_multipart::route::TYPED_MULTIPART,
532
            )
533
            .await?;
9✔
534
        // Modified
535
        test_executor
12✔
536
            .execute_modified::<TypedMultipart<ParametersValidify>>(
537
                Method::POST,
3✔
538
                typed_multipart::route::TYPED_MULTIPART_MODIFIED,
539
            )
540
            .await?;
9✔
541
        // ValidifiedByRef
542
        test_executor
12✔
543
            .execute::<TypedMultipart<ParametersValidify>>(
544
                Method::POST,
3✔
545
                typed_multipart::route::TYPED_MULTIPART_VALIDIFIED_BY_REF,
546
            )
547
            .await?;
9✔
548
    }
549

550
    #[cfg(feature = "extra")]
551
    {
552
        use axum_extra::extract::{Cached, WithRejection};
553
        use extra::{
554
            ParametersRejection, ValidifyWithRejectionRejection, WithRejectionValidifyRejection,
555
        };
556
        // Validated
557
        test_executor
12✔
558
            .execute::<Cached<ParametersValidify>>(Method::POST, extra::route::CACHED)
3✔
559
            .await?;
9✔
560
        // Modified
561
        test_executor
12✔
562
            .execute_modified::<Cached<ParametersValidify>>(
563
                Method::POST,
3✔
564
                extra::route::CACHED_MODIFIED,
565
            )
566
            .await?;
9✔
567
        // ValidifiedByRef
568
        test_executor
12✔
569
            .execute::<Cached<ParametersValidify>>(
570
                Method::POST,
3✔
571
                extra::route::CACHED_VALIDIFIED_BY_REF,
572
            )
573
            .await?;
9✔
574

575
        // Validated
576
        test_executor
12✔
577
            .execute::<WithRejection<ParametersValidify, ValidifyWithRejectionRejection>>(
578
                Method::POST,
3✔
579
                extra::route::WITH_REJECTION,
580
            )
581
            .await?;
9✔
582
        // Modified
583
        test_executor
12✔
584
            .execute_modified::<WithRejection<ParametersValidify, ValidifyWithRejectionRejection>>(
585
                Method::POST,
3✔
586
                extra::route::WITH_REJECTION_MODIFIED,
587
            )
588
            .await?;
9✔
589
        // ValidifiedByRef
590
        test_executor
12✔
591
            .execute::<WithRejection<ParametersValidify, ValidifyWithRejectionRejection>>(
592
                Method::POST,
3✔
593
                extra::route::WITH_REJECTION_VALIDIFIED_BY_REF,
594
            )
595
            .await?;
9✔
596

597
        test_executor
12✔
598
            .execute::<WithRejection<
599
                Validated<ParametersValidify>,
600
                WithRejectionValidifyRejection<ParametersRejection>,
601
            >>(Method::POST, extra::route::WITH_REJECTION_VALIDIFY)
3✔
602
            .await?;
9✔
603
    }
604

605
    #[cfg(feature = "extra_typed_path")]
606
    {
607
        async fn test_extra_typed_path(
3✔
608
            test_executor: &TestExecutor,
609
            route: &str,
610
            server_url: &str,
611
        ) -> anyhow::Result<()> {
612
            do_test_extra_typed_path(
613
                test_executor,
614
                route,
615
                server_url,
616
                StatusCode::OK,
617
                StatusCode::BAD_REQUEST,
618
                VALIDATION_ERROR_STATUS,
619
                true,
620
            )
621
            .await
9✔
622
        }
623

624
        async fn test_extra_typed_path_modified(
3✔
625
            test_executor: &TestExecutor,
626
            route: &str,
627
            server_url: &str,
628
        ) -> anyhow::Result<()> {
629
            do_test_extra_typed_path(
630
                test_executor,
631
                route,
632
                server_url,
633
                StatusCode::OK,
634
                StatusCode::BAD_REQUEST,
635
                StatusCode::OK,
636
                false,
637
            )
638
            .await
9✔
639
        }
640

641
        async fn do_test_extra_typed_path(
3✔
642
            test_executor: &TestExecutor,
643
            route: &str,
644
            server_url: &str,
645
            expected_valid_status: StatusCode,
646
            expected_error_status: StatusCode,
647
            expected_invalid_status: StatusCode,
648
            should_check_json: bool,
649
        ) -> anyhow::Result<()> {
650
            let extra_typed_path_type_name = "T: TypedPath";
3✔
651
            let valid_extra_typed_path_response = test_executor
12✔
652
                .client()
653
                .get(format!(
21✔
654
                    "{}/{route}/{}/{}",
655
                    server_url, VALID_PARAMETERS.v0, VALID_PARAMETERS.v1
6✔
656
                ))
657
                .send()
658
                .await?;
9✔
659
            assert_eq!(
3✔
660
                valid_extra_typed_path_response.status(),
6✔
661
                expected_valid_status,
662
                "Validified '{}' test failed.",
663
                extra_typed_path_type_name
664
            );
665

666
            let error_extra_typed_path_response = test_executor
12✔
667
                .client()
668
                .get(format!("{}/{route}/not_i32/path", server_url))
9✔
669
                .send()
670
                .await?;
9✔
671
            assert_eq!(
3✔
672
                error_extra_typed_path_response.status(),
6✔
673
                expected_error_status,
674
                "Error '{}' test failed.",
675
                extra_typed_path_type_name
676
            );
677

678
            let invalid_extra_typed_path_response = test_executor
12✔
679
                .client()
680
                .get(format!(
21✔
681
                    "{}/{route}/{}/{}",
682
                    server_url, INVALID_PARAMETERS.v0, INVALID_PARAMETERS.v1
6✔
683
                ))
684
                .send()
685
                .await?;
9✔
686
            assert_eq!(
3✔
687
                invalid_extra_typed_path_response.status(),
6✔
688
                expected_invalid_status,
689
                "Invalid '{}' test failed.",
690
                extra_typed_path_type_name
691
            );
692

693
            if should_check_json {
2✔
694
                #[cfg(feature = "into_json")]
695
                check_json(
696
                    extra_typed_path_type_name,
2✔
697
                    invalid_extra_typed_path_response,
2✔
698
                )
699
                .await;
2✔
700
            }
701
            println!("All {} tests passed.", extra_typed_path_type_name);
6✔
702
            Ok(())
3✔
703
        }
704

705
        test_extra_typed_path(&test_executor, "extra_typed_path", &server_url).await?;
9✔
706
        test_extra_typed_path_modified(&test_executor, "extra_typed_path_modified", &server_url)
12✔
707
            .await?;
9✔
708
        test_extra_typed_path(
709
            &test_executor,
3✔
710
            "extra_typed_path_validified_by_ref",
711
            &server_url,
3✔
712
        )
713
        .await?;
9✔
714
    }
715

716
    #[cfg(feature = "extra_query")]
717
    {
718
        use axum_extra::extract::Query;
719
        // Validated
720
        test_executor
12✔
721
            .execute::<Query<ParametersValidify>>(Method::POST, extra_query::route::EXTRA_QUERY)
3✔
722
            .await?;
9✔
723
        // Modified
724
        test_executor
12✔
725
            .execute_modified::<Query<ParametersValidify>>(
726
                Method::POST,
3✔
727
                extra_query::route::EXTRA_QUERY_MODIFIED,
728
            )
729
            .await?;
9✔
730
        // Validified
731
        test_executor
12✔
732
            .execute_validified::<Query<ParametersValidify>>(
733
                Method::POST,
3✔
734
                extra_query::route::EXTRA_QUERY_VALIDIFIED,
735
            )
736
            .await?;
9✔
737
        // ValidifiedByRef
738
        test_executor
12✔
739
            .execute::<Query<ParametersValidify>>(
740
                Method::POST,
3✔
741
                extra_query::route::EXTRA_QUERY_VALIDIFIED_BY_REF,
742
            )
743
            .await?;
9✔
744
    }
745

746
    #[cfg(feature = "extra_form")]
747
    {
748
        use axum_extra::extract::Form;
749
        // Validated
750
        test_executor
12✔
751
            .execute::<Form<ParametersValidify>>(Method::POST, extra_form::route::EXTRA_FORM)
3✔
752
            .await?;
9✔
753
        // Modified
754
        test_executor
12✔
755
            .execute_modified::<Form<ParametersValidify>>(
756
                Method::POST,
3✔
757
                extra_form::route::EXTRA_FORM_MODIFIED,
758
            )
759
            .await?;
9✔
760
        // Validified
761
        test_executor
12✔
762
            .execute_validified::<Form<ParametersValidify>>(
763
                Method::POST,
3✔
764
                extra_form::route::EXTRA_FORM_VALIDIFED,
765
            )
766
            .await?;
9✔
767
        // ValidifiedByRef
768
        test_executor
12✔
769
            .execute::<Form<ParametersValidify>>(
770
                Method::POST,
3✔
771
                extra_form::route::EXTRA_FORM_VALIDIFED_BY_REF,
772
            )
773
            .await?;
9✔
774
    }
775

776
    #[cfg(feature = "extra_protobuf")]
777
    {
778
        use axum_extra::protobuf::Protobuf;
779
        // Validated
780
        test_executor
12✔
781
            .execute::<Protobuf<ParametersValidify>>(
782
                Method::POST,
3✔
783
                extra_protobuf::route::EXTRA_PROTOBUF,
784
            )
785
            .await?;
9✔
786
        // Modified
787
        test_executor
12✔
788
            .execute_modified::<Protobuf<ParametersValidify>>(
789
                Method::POST,
3✔
790
                extra_protobuf::route::EXTRA_PROTOBUF_MODIFIED,
791
            )
792
            .await?;
9✔
793
        // ValidifiedByRef
794
        test_executor
12✔
795
            .execute::<Protobuf<ParametersValidify>>(
796
                Method::POST,
3✔
797
                extra_protobuf::route::EXTRA_PROTOBUF_VALIDIFIED_BY_REF,
798
            )
799
            .await?;
9✔
800
    }
801

802
    #[cfg(feature = "yaml")]
803
    {
804
        use axum_yaml::Yaml;
805

806
        // Validated
807
        test_executor
12✔
808
            .execute::<Yaml<ParametersValidify>>(Method::POST, yaml::route::YAML)
3✔
809
            .await?;
9✔
810
        // Modified
811
        test_executor
12✔
812
            .execute_modified::<Yaml<ParametersValidify>>(Method::POST, yaml::route::YAML_MODIFIED)
3✔
813
            .await?;
9✔
814
        // Validified
815
        test_executor
12✔
816
            .execute_validified::<Yaml<ParametersValidify>>(
817
                Method::POST,
3✔
818
                yaml::route::YAML_VALIDIFIED,
819
            )
820
            .await?;
9✔
821
        // ValidifiedByRef
822
        test_executor
12✔
823
            .execute::<Yaml<ParametersValidify>>(Method::POST, yaml::route::YAML_VALIDIFIED_BY_REF)
3✔
824
            .await?;
9✔
825
    }
826

827
    #[cfg(feature = "msgpack")]
828
    {
829
        use axum_msgpack::{MsgPack, MsgPackRaw};
830
        // Validated
831
        test_executor
12✔
832
            .execute::<MsgPack<ParametersValidify>>(Method::POST, msgpack::route::MSGPACK)
3✔
833
            .await?;
9✔
834
        // Modified
835
        test_executor
12✔
836
            .execute_modified::<MsgPack<ParametersValidify>>(
837
                Method::POST,
3✔
838
                msgpack::route::MSGPACK_MODIFIED,
839
            )
840
            .await?;
9✔
841
        // Validified
842
        test_executor
12✔
843
            .execute_validified::<MsgPack<ParametersValidify>>(
844
                Method::POST,
3✔
845
                msgpack::route::MSGPACK_VALIDIFIED,
846
            )
847
            .await?;
9✔
848
        // ValidifiedByRef
849
        test_executor
12✔
850
            .execute::<MsgPack<ParametersValidify>>(
851
                Method::POST,
3✔
852
                msgpack::route::MSGPACK_VALIDIFIED_BY_REF,
853
            )
854
            .await?;
9✔
855

856
        //
857
        test_executor
12✔
858
            .execute::<MsgPackRaw<ParametersValidify>>(Method::POST, msgpack::route::MSGPACK_RAW)
3✔
859
            .await?;
9✔
860
        //
861
        test_executor
12✔
862
            .execute_modified::<MsgPackRaw<ParametersValidify>>(
863
                Method::POST,
3✔
864
                msgpack::route::MSGPACK_RAW_MODIFIED,
865
            )
866
            .await?;
9✔
867
        //
868
        test_executor
12✔
869
            .execute_validified::<MsgPackRaw<ParametersValidify>>(
870
                Method::POST,
3✔
871
                msgpack::route::MSGPACK_RAW_VALIDIFIED,
872
            )
873
            .await?;
9✔
874
        //
875
        test_executor
12✔
876
            .execute::<MsgPackRaw<ParametersValidify>>(
877
                Method::POST,
3✔
878
                msgpack::route::MSGPACK_RAW_VALIDIFIED_BY_REF,
879
            )
880
            .await?;
9✔
881
    }
882

883
    drop(server_guard);
3✔
884
    server_handle.await??;
6✔
885
    Ok(())
6✔
886
}
887

888
#[derive(Debug, Clone)]
889
pub struct TestExecutor {
890
    client: reqwest::Client,
891
    server_url: Url,
892
}
893

894
impl From<Url> for TestExecutor {
895
    fn from(server_url: Url) -> Self {
3✔
896
        Self {
897
            client: Default::default(),
3✔
898
            server_url,
899
        }
900
    }
901
}
902

903
impl TestExecutor {
904
    /// Execute all tests
905
    pub async fn execute<T: ValidTest>(&self, method: Method, route: &str) -> anyhow::Result<()> {
225✔
906
        self.do_execute::<T>(
90✔
907
            method,
×
908
            route,
×
909
            StatusCode::OK,
×
910
            T::ERROR_STATUS_CODE,
×
911
            T::INVALID_STATUS_CODE,
×
912
            true,
913
        )
914
        .await
135✔
915
    }
916

917
    /// Execute all tests for `Modified` without validation
918
    pub async fn execute_modified<T: ValidTest>(
42✔
919
        &self,
920
        method: Method,
921
        route: &str,
922
    ) -> anyhow::Result<()> {
923
        self.do_execute::<T>(
84✔
924
            method,
×
925
            route,
×
926
            StatusCode::OK,
×
927
            T::ERROR_STATUS_CODE,
×
928
            StatusCode::OK,
×
929
            false,
930
        )
931
        .await
126✔
932
    }
933

934
    /// Execute all tests for `Modified` without validation
935
    pub async fn execute_validified<T: ValidTest>(
24✔
936
        &self,
937
        method: Method,
938
        route: &str,
939
    ) -> anyhow::Result<()> {
940
        self.do_execute::<T>(
48✔
941
            method,
×
942
            route,
×
943
            StatusCode::OK,
×
944
            T::INVALID_STATUS_CODE,
×
945
            T::INVALID_STATUS_CODE,
×
946
            false,
947
        )
948
        .await
72✔
949
    }
950

951
    async fn do_execute<T: ValidTest>(
45✔
952
        &self,
953
        method: Method,
954
        route: &str,
955
        expected_valid_status: StatusCode,
956
        expected_error_status: StatusCode,
957
        expected_invalid_status: StatusCode,
958
        should_check_json: bool,
959
    ) -> anyhow::Result<()> {
960
        let url = {
×
961
            let mut url_builder = self.server_url.clone();
45✔
962
            url_builder.set_path(route);
45✔
963
            url_builder
45✔
964
        };
965

966
        let type_name = type_name::<T>();
90✔
967

968
        let valid_builder = self.client.request(method.clone(), url.clone());
90✔
969
        let valid_response = T::set_valid_request(valid_builder).send().await?;
135✔
970
        assert_eq!(
45✔
971
            valid_response.status(),
90✔
972
            expected_valid_status,
×
973
            "Validified '{}' test failed: {}.",
974
            type_name,
×
975
            valid_response.text().await?
×
976
        );
977

978
        let error_builder = self.client.request(method.clone(), url.clone());
90✔
979
        let error_response = T::set_error_request(error_builder).send().await?;
135✔
980
        assert_eq!(
45✔
981
            error_response.status(),
90✔
982
            expected_error_status,
×
983
            "Error '{}' test failed: {}.",
984
            type_name,
×
985
            error_response.text().await?
×
986
        );
987

988
        let invalid_builder = self.client.request(method, url);
45✔
989
        let invalid_response = T::set_invalid_request(invalid_builder).send().await?;
135✔
990
        assert_eq!(
45✔
991
            invalid_response.status(),
90✔
992
            expected_invalid_status,
×
993
            "Invalid '{}' test failed: {}.",
994
            type_name,
×
995
            invalid_response.text().await?
×
996
        );
997
        if should_check_json {
30✔
998
            #[cfg(feature = "into_json")]
×
999
            if T::JSON_SERIALIZABLE {
30✔
1000
                check_json(type_name, invalid_response).await;
28✔
1001
            }
1002
        }
1003

1004
        println!("All '{}' tests passed.", type_name);
90✔
1005
        Ok(())
45✔
1006
    }
1007

1008
    pub fn client(&self) -> &reqwest::Client {
3✔
1009
        &self.client
3✔
1010
    }
1011
}
1012

1013
/// Check if the response is a json response
1014
#[cfg(feature = "into_json")]
1015
pub async fn check_json(type_name: &'static str, response: reqwest::Response) {
12✔
1016
    assert_eq!(
2✔
1017
        response.headers()[axum::http::header::CONTENT_TYPE],
4✔
1018
        axum::http::HeaderValue::from_static(mime::APPLICATION_JSON.as_ref()),
2✔
1019
        "'{}' rejection into json test failed",
1020
        type_name
1021
    );
1022
    assert!(response.json::<serde_json::Value>().await.is_ok());
2✔
1023
}
1024

1025
mod route {
1026
    pub const PATH: &str = "/path/:v0/:v1";
1027
    pub const PATH_MODIFIED: &str = "/path_modified/:v0/:v1";
1028
    pub const PATH_VALIDIFIED: &str = "/path_validified/:v0/:v1";
1029
    pub const PATH_VALIDIFIED_BY_REF: &str = "/path_validified_by_ref/:v0/:v1";
1030
    pub const QUERY: &str = "/query";
1031
    pub const QUERY_MODIFIED: &str = "/query_modified/:v0/:v1";
1032

1033
    pub const QUERY_VALIDIFIED: &str = "/query_validified/:v0/:v1";
1034
    pub const QUERY_VALIDIFIED_BY_REF: &str = "/query_validified_by_ref/:v0/:v1";
1035
    pub const FORM: &str = "/form";
1036
    pub const FORM_MODIFIED: &str = "/form_modified/:v0/:v1";
1037
    pub const FORM_VALIDIFIED: &str = "/form_validified/:v0/:v1";
1038
    pub const FORM_VALIDIFIED_BY_REF: &str = "/form_validified_by_ref/:v0/:v1";
1039
    pub const JSON: &str = "/json";
1040
    pub const JSON_MODIFIED: &str = "/json_modified/:v0/:v1";
1041
    pub const JSON_VALIDIFIED: &str = "/json_validified/:v0/:v1";
1042
    pub const JSON_VALIDIFIED_BY_REF: &str = "/json_validified_by_ref/:v0/:v1";
1043
}
1044

1045
async fn extract_path(
3✔
1046
    Validated(Path(parameters)): Validated<Path<ParametersValidify>>,
1047
) -> StatusCode {
1048
    check_validated(&parameters)
3✔
1049
}
1050

1051
async fn extract_path_modified(
3✔
1052
    Modified(Path(parameters)): Modified<Path<ParametersValidify>>,
1053
) -> StatusCode {
1054
    check_modified(&parameters)
3✔
1055
}
1056

1057
async fn extract_path_validified(
3✔
1058
    Validified(Path(parameters)): Validified<Path<ParametersValidify>>,
1059
) -> StatusCode {
1060
    check_validified(&parameters)
3✔
1061
}
1062

1063
async fn extract_path_validified_by_ref(
3✔
1064
    ValidifiedByRef(Path(parameters)): ValidifiedByRef<Path<ParametersValidify>>,
1065
) -> StatusCode {
1066
    check_validified(&parameters)
3✔
1067
}
1068

1069
async fn extract_query(
3✔
1070
    Validated(Query(parameters)): Validated<Query<ParametersValidify>>,
1071
) -> StatusCode {
1072
    check_validated(&parameters)
3✔
1073
}
1074

1075
async fn extract_query_modified(
3✔
1076
    Modified(Query(parameters)): Modified<Query<ParametersValidify>>,
1077
) -> StatusCode {
1078
    check_modified(&parameters)
3✔
1079
}
1080

1081
async fn extract_query_validified(
3✔
1082
    Validified(Query(parameters)): Validified<Query<ParametersValidify>>,
1083
) -> StatusCode {
1084
    check_validified(&parameters)
3✔
1085
}
1086

1087
async fn extract_query_validified_by_ref(
3✔
1088
    ValidifiedByRef(Query(parameters)): ValidifiedByRef<Query<ParametersValidify>>,
1089
) -> StatusCode {
1090
    check_validified(&parameters)
3✔
1091
}
1092

1093
async fn extract_form(
3✔
1094
    Validated(Form(parameters)): Validated<Form<ParametersValidify>>,
1095
) -> StatusCode {
1096
    check_validated(&parameters)
3✔
1097
}
1098

1099
async fn extract_form_modified(
3✔
1100
    Modified(Form(parameters)): Modified<Form<ParametersValidify>>,
1101
) -> StatusCode {
1102
    check_modified(&parameters)
3✔
1103
}
1104

1105
async fn extract_form_validified(
3✔
1106
    Validified(Form(parameters)): Validified<Form<ParametersValidify>>,
1107
) -> StatusCode {
1108
    check_validified(&parameters)
3✔
1109
}
1110

1111
async fn extract_form_validified_by_ref(
3✔
1112
    ValidifiedByRef(Form(parameters)): ValidifiedByRef<Form<ParametersValidify>>,
1113
) -> StatusCode {
1114
    check_validified(&parameters)
3✔
1115
}
1116

1117
async fn extract_json(
3✔
1118
    Validated(Json(parameters)): Validated<Json<ParametersValidify>>,
1119
) -> StatusCode {
1120
    check_validated(&parameters)
3✔
1121
}
1122

1123
async fn extract_json_modified(
3✔
1124
    Modified(Json(parameters)): Modified<Json<ParametersValidify>>,
1125
) -> StatusCode {
1126
    check_modified(&parameters)
3✔
1127
}
1128

1129
async fn extract_json_validified(
3✔
1130
    Validified(Json(parameters)): Validified<Json<ParametersValidify>>,
1131
) -> StatusCode {
1132
    check_validified(&parameters)
3✔
1133
}
1134

1135
async fn extract_json_validified_by_ref(
3✔
1136
    ValidifiedByRef(Json(parameters)): ValidifiedByRef<Json<ParametersValidify>>,
1137
) -> StatusCode {
1138
    check_validified(&parameters)
3✔
1139
}
1140

1141
fn check_validated<V: Validate>(validate: &V) -> StatusCode {
9✔
1142
    // The `Validified` extractor has validated the `parameters` once,
1143
    // it should have returned `400 BAD REQUEST` if the `parameters` were invalid,
1144
    // Let's validate them again to check if the `Validated` extractor works well.
1145
    // If it works properly, this function will never return `500 INTERNAL SERVER ERROR`
1146
    match validate.validate() {
9✔
1147
        Ok(_) => StatusCode::OK,
9✔
1148
        Err(e) => {
×
1149
            eprintln!("Data is unvalidated: {e}");
×
1150
            StatusCode::INTERNAL_SERVER_ERROR
×
1151
        }
1152
    }
1153
}
1154

1155
fn check_modified<M: IsModified>(modify: &M) -> StatusCode {
9✔
1156
    if modify.modified() {
9✔
1157
        StatusCode::OK
9✔
1158
    } else {
1159
        StatusCode::INTERNAL_SERVER_ERROR
×
1160
    }
1161
}
1162

1163
fn check_validified<D: IsModified + Validate>(data: &D) -> StatusCode {
6✔
1164
    let status = check_modified(data);
6✔
1165
    if status != StatusCode::OK {
6✔
1166
        return status;
×
1167
    }
1168

1169
    check_validated(data)
6✔
1170
}
1171

1172
#[cfg(feature = "typed_header")]
1173
mod typed_header {
1174

1175
    pub(crate) mod route {
1176
        pub const TYPED_HEADER: &str = "/typed_header";
1177
        pub const TYPED_HEADER_MODIFIED: &str = "/typed_header_modified";
1178
        pub const TYPED_HEADER_VALIDIFIED_BY_REF: &str = "/typed_header_validified_be_ref";
1179
    }
1180

1181
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
1182
    use crate::{Modified, Validated, ValidifiedByRef};
1183
    use axum::headers::{Error, Header, HeaderName, HeaderValue};
1184
    use axum::http::StatusCode;
1185
    use axum::TypedHeader;
1186

1187
    pub static AXUM_VALID_PARAMETERS: HeaderName = HeaderName::from_static("axum-valid-parameters");
1188

1189
    pub(super) async fn extract_typed_header(
3✔
1190
        Validated(TypedHeader(parameters)): Validated<TypedHeader<ParametersValidify>>,
1191
    ) -> StatusCode {
1192
        check_validated(&parameters)
3✔
1193
    }
1194

1195
    pub(super) async fn extract_typed_header_modified(
3✔
1196
        Modified(TypedHeader(parameters)): Modified<TypedHeader<ParametersValidify>>,
1197
    ) -> StatusCode {
1198
        check_modified(&parameters)
3✔
1199
    }
1200

1201
    pub(super) async fn extract_typed_header_validified_by_ref(
3✔
1202
        ValidifiedByRef(TypedHeader(parameters)): ValidifiedByRef<TypedHeader<ParametersValidify>>,
1203
    ) -> StatusCode {
1204
        check_validified(&parameters)
3✔
1205
    }
1206

1207
    impl Header for ParametersValidify {
1208
        fn name() -> &'static HeaderName {
1209
            &AXUM_VALID_PARAMETERS
1210
        }
1211

1212
        fn decode<'i, I>(values: &mut I) -> Result<Self, Error>
6✔
1213
        where
1214
            Self: Sized,
1215
            I: Iterator<Item = &'i HeaderValue>,
1216
        {
1217
            let value = values.next().ok_or_else(Error::invalid)?;
9✔
1218
            let src = std::str::from_utf8(value.as_bytes()).map_err(|_| Error::invalid())?;
12✔
1219
            let split = src.split(',').collect::<Vec<_>>();
6✔
1220
            match split.as_slice() {
6✔
1221
                [v0, v1] => Ok(ParametersValidify {
18✔
1222
                    v0: v0.parse().map_err(|_| Error::invalid())?,
18✔
1223
                    v1: v1.to_string(),
6✔
1224
                }),
1225
                _ => Err(Error::invalid()),
×
1226
            }
1227
        }
1228

1229
        fn encode<E: Extend<HeaderValue>>(&self, values: &mut E) {
6✔
1230
            let v0 = self.v0.to_string();
6✔
1231
            let mut vec = Vec::with_capacity(v0.len() + 1 + self.v1.len());
12✔
1232
            vec.extend_from_slice(v0.as_bytes());
12✔
1233
            vec.push(b',');
6✔
1234
            vec.extend_from_slice(self.v1.as_bytes());
6✔
1235
            let value = HeaderValue::from_bytes(&vec).expect("Failed to build header");
6✔
1236
            values.extend(::std::iter::once(value));
6✔
1237
        }
1238
    }
1239

1240
    #[test]
1241
    fn parameter_is_header() -> anyhow::Result<()> {
1242
        let parameter = ParametersValidify {
1243
            v0: 123456,
1244
            v1: "111111".to_string(),
1245
        };
1246
        let mut vec = Vec::new();
1247
        parameter.encode(&mut vec);
1248
        let mut iter = vec.iter();
1249
        assert_eq!(parameter, ParametersValidify::decode(&mut iter)?);
1250
        Ok(())
1251
    }
1252
}
1253

1254
#[cfg(feature = "typed_multipart")]
1255
mod typed_multipart {
1256
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
1257
    use crate::{Modified, Validated, ValidifiedByRef};
1258
    use axum::http::StatusCode;
1259
    use axum_typed_multipart::{BaseMultipart, TypedMultipart, TypedMultipartError};
1260

1261
    pub mod route {
1262
        pub const TYPED_MULTIPART: &str = "/typed_multipart";
1263
        pub const TYPED_MULTIPART_MODIFIED: &str = "/typed_multipart_modified";
1264
        pub const TYPED_MULTIPART_VALIDIFIED_BY_REF: &str = "/typed_multipart_validified_by_ref";
1265

1266
        pub const BASE_MULTIPART: &str = "/base_multipart";
1267
        pub const BASE_MULTIPART_MODIFIED: &str = "/base_multipart_modified";
1268
        pub const BASE_MULTIPART_VALIDIFIED_BY_REF: &str = "/base_multipart_validified_by_ref";
1269
    }
1270

1271
    impl From<&ParametersValidify> for reqwest::multipart::Form {
1272
        fn from(value: &ParametersValidify) -> Self {
3✔
1273
            reqwest::multipart::Form::new()
9✔
1274
                .text("v0", value.v0.to_string())
6✔
1275
                .text("v1", value.v1.clone())
6✔
1276
        }
1277
    }
1278

1279
    pub(super) async fn extract_typed_multipart(
3✔
1280
        Validated(TypedMultipart(parameters)): Validated<TypedMultipart<ParametersValidify>>,
1281
    ) -> StatusCode {
1282
        check_validated(&parameters)
3✔
1283
    }
1284

1285
    pub(super) async fn extract_typed_multipart_modified(
3✔
1286
        Modified(TypedMultipart(parameters)): Modified<TypedMultipart<ParametersValidify>>,
1287
    ) -> StatusCode {
1288
        check_modified(&parameters)
3✔
1289
    }
1290

1291
    pub(super) async fn extract_typed_multipart_validified_by_ref(
3✔
1292
        ValidifiedByRef(TypedMultipart(parameters)): ValidifiedByRef<
1293
            TypedMultipart<ParametersValidify>,
1294
        >,
1295
    ) -> StatusCode {
1296
        check_validified(&parameters)
3✔
1297
    }
1298

1299
    pub(super) async fn extract_base_multipart(
3✔
1300
        Validated(BaseMultipart { data, .. }): Validated<
1301
            BaseMultipart<ParametersValidify, TypedMultipartError>,
1302
        >,
1303
    ) -> StatusCode {
1304
        check_validated(&data)
3✔
1305
    }
1306

1307
    pub(super) async fn extract_base_multipart_modified(
3✔
1308
        Modified(BaseMultipart { data, .. }): Modified<
1309
            BaseMultipart<ParametersValidify, TypedMultipartError>,
1310
        >,
1311
    ) -> StatusCode {
1312
        check_modified(&data)
3✔
1313
    }
1314

1315
    pub(super) async fn extract_base_multipart_validified_by_ref(
3✔
1316
        ValidifiedByRef(BaseMultipart { data, .. }): ValidifiedByRef<
1317
            BaseMultipart<ParametersValidify, TypedMultipartError>,
1318
        >,
1319
    ) -> StatusCode {
1320
        check_validified(&data)
3✔
1321
    }
1322
}
1323

1324
#[cfg(feature = "extra")]
1325
mod extra {
1326
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
1327
    use crate::tests::{Rejection, ValidTest, ValidTestParameter};
1328
    use crate::{Modified, Validated, ValidifiedByRef, ValidifyRejection};
1329
    use axum::extract::FromRequestParts;
1330
    use axum::http::request::Parts;
1331
    use axum::http::StatusCode;
1332
    use axum::response::{IntoResponse, Response};
1333
    use axum_extra::extract::{Cached, WithRejection};
1334
    use reqwest::RequestBuilder;
1335

1336
    pub mod route {
1337
        pub const CACHED: &str = "/cached";
1338
        pub const CACHED_MODIFIED: &str = "/cached_modified";
1339
        pub const CACHED_VALIDIFIED_BY_REF: &str = "/cached_validified_by_ref";
1340
        pub const WITH_REJECTION: &str = "/with_rejection";
1341
        pub const WITH_REJECTION_MODIFIED: &str = "/with_rejection_modified";
1342
        pub const WITH_REJECTION_VALIDIFIED_BY_REF: &str = "/with_rejection_validified_by_ref";
1343
        pub const WITH_REJECTION_VALIDIFY: &str = "/with_rejection_validify";
1344
    }
1345
    pub const PARAMETERS_HEADER: &str = "parameters-header";
1346
    pub const CACHED_REJECTION_STATUS: StatusCode = StatusCode::FORBIDDEN;
1347

1348
    //  1.2. Define you own `Rejection` type and implement `IntoResponse` for it.
1349
    pub enum ParametersRejection {
1350
        Null,
1351
        InvalidJson(serde_json::error::Error),
1352
    }
1353

1354
    impl IntoResponse for ParametersRejection {
1355
        fn into_response(self) -> Response {
3✔
1356
            match self {
3✔
1357
                ParametersRejection::Null => {
1358
                    (CACHED_REJECTION_STATUS, "My-Data header is missing").into_response()
×
1359
                }
1360
                ParametersRejection::InvalidJson(e) => (
6✔
1361
                    CACHED_REJECTION_STATUS,
1362
                    format!("My-Data is not valid json string: {e}"),
3✔
1363
                )
1364
                    .into_response(),
1365
            }
1366
        }
1367
    }
1368

1369
    //  1.3. Implement your extractor (`FromRequestParts` or `FromRequest`)
1370
    #[axum::async_trait]
1371
    impl<S> FromRequestParts<S> for ParametersValidify
1372
    where
1373
        S: Send + Sync,
1374
    {
1375
        type Rejection = ParametersRejection;
1376

1377
        async fn from_request_parts(parts: &mut Parts, _: &S) -> Result<Self, Self::Rejection> {
15✔
1378
            let Some(value) = parts.headers.get(PARAMETERS_HEADER) else {
3✔
1379
                return Err(ParametersRejection::Null);
×
1380
            };
1381

1382
            serde_json::from_slice(value.as_bytes()).map_err(ParametersRejection::InvalidJson)
6✔
1383
        }
1384
    }
1385

1386
    impl ValidTest for ParametersValidify {
1387
        const ERROR_STATUS_CODE: StatusCode = CACHED_REJECTION_STATUS;
1388

1389
        fn set_valid_request(builder: RequestBuilder) -> RequestBuilder {
3✔
1390
            builder.header(
6✔
1391
                PARAMETERS_HEADER,
1392
                serde_json::to_string(ParametersValidify::valid())
6✔
1393
                    .expect("Failed to serialize parameters"),
1394
            )
1395
        }
1396

1397
        fn set_error_request(builder: RequestBuilder) -> RequestBuilder {
3✔
1398
            builder.header(
6✔
1399
                PARAMETERS_HEADER,
1400
                serde_json::to_string(ParametersValidify::error())
6✔
1401
                    .expect("Failed to serialize parameters"),
1402
            )
1403
        }
1404

1405
        fn set_invalid_request(builder: RequestBuilder) -> RequestBuilder {
3✔
1406
            builder.header(
6✔
1407
                PARAMETERS_HEADER,
1408
                serde_json::to_string(ParametersValidify::invalid())
6✔
1409
                    .expect("Failed to serialize parameters"),
1410
            )
1411
        }
1412
    }
1413

1414
    pub struct ValidifyWithRejectionRejection {
1415
        inner: ParametersRejection,
1416
    }
1417

1418
    impl Rejection for ValidifyWithRejectionRejection {
1419
        const STATUS_CODE: StatusCode = StatusCode::CONFLICT;
1420
    }
1421

1422
    impl IntoResponse for ValidifyWithRejectionRejection {
1423
        fn into_response(self) -> Response {
3✔
1424
            let mut response = self.inner.into_response();
3✔
1425
            *response.status_mut() = Self::STATUS_CODE;
6✔
1426
            response
3✔
1427
        }
1428
    }
1429

1430
    // satisfy the `WithRejection`'s extractor trait bound
1431
    // R: From<E::Rejection> + IntoResponse
1432
    impl From<ParametersRejection> for ValidifyWithRejectionRejection {
1433
        fn from(inner: ParametersRejection) -> Self {
3✔
1434
            Self { inner }
1435
        }
1436
    }
1437

1438
    pub async fn extract_cached(
3✔
1439
        Validated(Cached(parameters)): Validated<Cached<ParametersValidify>>,
1440
    ) -> StatusCode {
1441
        check_validated(&parameters)
3✔
1442
    }
1443

1444
    pub async fn extract_cached_modified(
3✔
1445
        Modified(Cached(parameters)): Modified<Cached<ParametersValidify>>,
1446
    ) -> StatusCode {
1447
        check_modified(&parameters)
3✔
1448
    }
1449

1450
    pub async fn extract_cached_validified_by_ref(
3✔
1451
        ValidifiedByRef(Cached(parameters)): ValidifiedByRef<Cached<ParametersValidify>>,
1452
    ) -> StatusCode {
1453
        check_validified(&parameters)
3✔
1454
    }
1455

1456
    pub async fn extract_with_rejection(
3✔
1457
        Validated(WithRejection(parameters, _)): Validated<
1458
            WithRejection<ParametersValidify, ValidifyWithRejectionRejection>,
1459
        >,
1460
    ) -> StatusCode {
1461
        check_validated(&parameters)
3✔
1462
    }
1463

1464
    pub async fn extract_with_rejection_modified(
3✔
1465
        Modified(WithRejection(parameters, _)): Modified<
1466
            WithRejection<ParametersValidify, ValidifyWithRejectionRejection>,
1467
        >,
1468
    ) -> StatusCode {
1469
        check_modified(&parameters)
3✔
1470
    }
1471

1472
    pub async fn extract_with_rejection_validified_by_ref(
3✔
1473
        ValidifiedByRef(WithRejection(parameters, _)): ValidifiedByRef<
1474
            WithRejection<ParametersValidify, ValidifyWithRejectionRejection>,
1475
        >,
1476
    ) -> StatusCode {
1477
        check_validified(&parameters)
3✔
1478
    }
1479

1480
    pub struct WithRejectionValidifyRejection<E> {
1481
        inner: ValidifyRejection<E>,
1482
    }
1483

1484
    impl<E> From<ValidifyRejection<E>> for WithRejectionValidifyRejection<E> {
1485
        fn from(inner: ValidifyRejection<E>) -> Self {
3✔
1486
            Self { inner }
1487
        }
1488
    }
1489

1490
    impl<E: IntoResponse> IntoResponse for WithRejectionValidifyRejection<E> {
1491
        fn into_response(self) -> Response {
3✔
1492
            let mut res = self.inner.into_response();
3✔
1493
            *res.status_mut() = StatusCode::IM_A_TEAPOT;
6✔
1494
            res
3✔
1495
        }
1496
    }
1497

1498
    pub async fn extract_with_rejection_valid(
3✔
1499
        WithRejection(Validated(parameters), _): WithRejection<
1500
            Validated<ParametersValidify>,
1501
            WithRejectionValidifyRejection<ParametersRejection>,
1502
        >,
1503
    ) -> StatusCode {
1504
        check_validated(&parameters)
3✔
1505
    }
1506
}
1507

1508
#[cfg(feature = "extra_typed_path")]
1509
mod extra_typed_path {
1510
    use super::{check_modified, check_validated, check_validified};
1511
    use crate::{HasModify, HasValidate, Modified, Validated, ValidifiedByRef};
1512
    use axum::http::StatusCode;
1513
    use axum_extra::routing::TypedPath;
1514
    use serde::Deserialize;
1515
    use validify::{Validate, Validify};
1516

1517
    pub mod route {
1518
        pub const EXTRA_TYPED_PATH: &str = "/extra_typed_path/:v0/:v1";
1519
        pub const EXTRA_TYPED_PATH_MODIFIED: &str = "/extra_typed_path_modified/:v0/:v1";
1520
        pub const EXTRA_TYPED_PATH_VALIDIFIED_BY_REF: &str =
1521
            "/extra_typed_path_validified_by_ref/:v0/:v1";
1522
    }
1523

1524
    #[derive(Validate, TypedPath, Deserialize)]
1525
    #[typed_path("/extra_typed_path/:v0/:v1")]
1526
    pub struct TypedPathParam {
1527
        #[validate(range(min = 5.0, max = 10.0))]
1528
        v0: i32,
1529
        #[validate(length(min = 1, max = 10))]
1530
        v1: String,
1531
    }
1532

1533
    impl HasValidate for TypedPathParam {
1534
        type Validate = Self;
1535

1536
        fn get_validate(&self) -> &Self::Validate {
3✔
1537
            self
1538
        }
1539
    }
1540

1541
    #[derive(Validify, TypedPath, Deserialize, Clone, PartialEq, Eq)]
1542
    #[typed_path("/extra_typed_path_validified_by_ref/:v0/:v1")]
1543
    pub struct TypedPathParamValidifiedByRef {
1544
        #[validate(range(min = 5.0, max = 10.0))]
1545
        v0: i32,
1546
        #[modify(lowercase)]
1547
        #[validate(length(min = 1, max = 10))]
1548
        v1: String,
1549
    }
1550

1551
    impl HasValidate for TypedPathParamValidifiedByRef {
1552
        type Validate = Self;
1553

1554
        fn get_validate(&self) -> &Self::Validate {
3✔
1555
            self
1556
        }
1557
    }
1558

1559
    impl HasModify for TypedPathParamValidifiedByRef {
1560
        type Modify = Self;
1561

1562
        fn get_modify(&mut self) -> &mut Self::Modify {
3✔
1563
            self
1564
        }
1565
    }
1566

1567
    #[derive(Validify, TypedPath, Deserialize, Clone, PartialEq, Eq)]
1568
    #[typed_path("/extra_typed_path_modified/:v0/:v1")]
1569
    pub struct TypedPathParamModified {
1570
        #[validate(range(min = 5.0, max = 10.0))]
1571
        v0: i32,
1572
        #[modify(lowercase)]
1573
        #[validate(length(min = 1, max = 10))]
1574
        v1: String,
1575
    }
1576

1577
    impl HasModify for TypedPathParamModified {
1578
        type Modify = Self;
1579

1580
        fn get_modify(&mut self) -> &mut Self::Modify {
3✔
1581
            self
1582
        }
1583
    }
1584

1585
    pub async fn extract_extra_typed_path(
3✔
1586
        Validated(param): Validated<TypedPathParam>,
1587
    ) -> StatusCode {
1588
        check_validated(&param)
3✔
1589
    }
1590

1591
    pub async fn extract_extra_typed_path_modified(
3✔
1592
        Modified(param): Modified<TypedPathParamModified>,
1593
    ) -> StatusCode {
1594
        check_modified(&param)
3✔
1595
    }
1596

1597
    pub async fn extract_extra_typed_path_validified_by_ref(
3✔
1598
        ValidifiedByRef(param): ValidifiedByRef<TypedPathParamValidifiedByRef>,
1599
    ) -> StatusCode {
1600
        check_validified(&param)
3✔
1601
    }
1602
}
1603

1604
#[cfg(feature = "extra_query")]
1605
mod extra_query {
1606
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
1607
    use crate::{Modified, Validated, Validified, ValidifiedByRef};
1608
    use axum::http::StatusCode;
1609
    use axum_extra::extract::Query;
1610

1611
    pub mod route {
1612
        pub const EXTRA_QUERY: &str = "/extra_query";
1613
        pub const EXTRA_QUERY_MODIFIED: &str = "/extra_query_modified";
1614
        pub const EXTRA_QUERY_VALIDIFIED: &str = "/extra_query_validified";
1615
        pub const EXTRA_QUERY_VALIDIFIED_BY_REF: &str = "/extra_query_validified_by_ref";
1616
    }
1617

1618
    pub async fn extract_extra_query(
3✔
1619
        Validated(Query(parameters)): Validated<Query<ParametersValidify>>,
1620
    ) -> StatusCode {
1621
        check_validated(&parameters)
3✔
1622
    }
1623

1624
    pub async fn extract_extra_query_modified(
3✔
1625
        Modified(Query(parameters)): Modified<Query<ParametersValidify>>,
1626
    ) -> StatusCode {
1627
        check_modified(&parameters)
3✔
1628
    }
1629

1630
    pub async fn extract_extra_query_validified(
3✔
1631
        Validified(Query(parameters)): Validified<Query<ParametersValidify>>,
1632
    ) -> StatusCode {
1633
        check_validified(&parameters)
3✔
1634
    }
1635

1636
    pub async fn extract_extra_query_validified_by_ref(
3✔
1637
        ValidifiedByRef(Query(parameters)): ValidifiedByRef<Query<ParametersValidify>>,
1638
    ) -> StatusCode {
1639
        check_validified(&parameters)
3✔
1640
    }
1641
}
1642

1643
#[cfg(feature = "extra_form")]
1644
mod extra_form {
1645
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
1646
    use crate::{Modified, Validated, Validified, ValidifiedByRef};
1647
    use axum::http::StatusCode;
1648
    use axum_extra::extract::Form;
1649

1650
    pub mod route {
1651
        pub const EXTRA_FORM: &str = "/extra_form";
1652
        pub const EXTRA_FORM_MODIFIED: &str = "/extra_form_modified";
1653
        pub const EXTRA_FORM_VALIDIFED: &str = "/extra_form_validifed";
1654
        pub const EXTRA_FORM_VALIDIFED_BY_REF: &str = "/extra_form_validified_by_ref";
1655
    }
1656

1657
    pub async fn extract_extra_form(
3✔
1658
        Validated(Form(parameters)): Validated<Form<ParametersValidify>>,
1659
    ) -> StatusCode {
1660
        check_validated(&parameters)
3✔
1661
    }
1662

1663
    pub async fn extract_extra_form_modified(
3✔
1664
        Modified(Form(parameters)): Modified<Form<ParametersValidify>>,
1665
    ) -> StatusCode {
1666
        check_modified(&parameters)
3✔
1667
    }
1668

1669
    pub async fn extract_extra_form_validifed(
3✔
1670
        Validified(Form(parameters)): Validified<Form<ParametersValidify>>,
1671
    ) -> StatusCode {
1672
        check_validified(&parameters)
3✔
1673
    }
1674

1675
    pub async fn extract_extra_form_validifed_by_ref(
3✔
1676
        ValidifiedByRef(Form(parameters)): ValidifiedByRef<Form<ParametersValidify>>,
1677
    ) -> StatusCode {
1678
        check_validified(&parameters)
3✔
1679
    }
1680
}
1681

1682
#[cfg(feature = "extra_protobuf")]
1683
mod extra_protobuf {
1684
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
1685
    use crate::{Modified, Validated, ValidifiedByRef};
1686
    use axum::http::StatusCode;
1687
    use axum_extra::protobuf::Protobuf;
1688

1689
    pub mod route {
1690
        pub const EXTRA_PROTOBUF: &str = "/extra_protobuf";
1691
        pub const EXTRA_PROTOBUF_MODIFIED: &str = "/extra_protobuf_modified";
1692
        pub const EXTRA_PROTOBUF_VALIDIFIED_BY_REF: &str = "/extra_protobuf_validified_by_ref";
1693
    }
1694

1695
    pub async fn extract_extra_protobuf(
3✔
1696
        Validated(Protobuf(parameters)): Validated<Protobuf<ParametersValidify>>,
1697
    ) -> StatusCode {
1698
        check_validated(&parameters)
3✔
1699
    }
1700

1701
    pub async fn extract_extra_protobuf_modified(
3✔
1702
        Modified(Protobuf(parameters)): Modified<Protobuf<ParametersValidify>>,
1703
    ) -> StatusCode {
1704
        check_modified(&parameters)
3✔
1705
    }
1706

1707
    pub async fn extract_extra_protobuf_validified_by_ref(
3✔
1708
        ValidifiedByRef(Protobuf(parameters)): ValidifiedByRef<Protobuf<ParametersValidify>>,
1709
    ) -> StatusCode {
1710
        check_validified(&parameters)
3✔
1711
    }
1712
}
1713

1714
#[cfg(feature = "yaml")]
1715
mod yaml {
1716
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
1717
    use crate::{Modified, Validated, Validified, ValidifiedByRef};
1718
    use axum::http::StatusCode;
1719
    use axum_yaml::Yaml;
1720

1721
    pub mod route {
1722
        pub const YAML: &str = "/yaml";
1723
        pub const YAML_MODIFIED: &str = "/yaml_modified";
1724
        pub const YAML_VALIDIFIED: &str = "/yaml_validified";
1725
        pub const YAML_VALIDIFIED_BY_REF: &str = "/yaml_validified_by_ref";
1726
    }
1727

1728
    pub async fn extract_yaml(
3✔
1729
        Validated(Yaml(parameters)): Validated<Yaml<ParametersValidify>>,
1730
    ) -> StatusCode {
1731
        check_validated(&parameters)
3✔
1732
    }
1733

1734
    pub async fn extract_yaml_modified(
3✔
1735
        Modified(Yaml(parameters)): Modified<Yaml<ParametersValidify>>,
1736
    ) -> StatusCode {
1737
        check_modified(&parameters)
3✔
1738
    }
1739

1740
    pub async fn extract_yaml_validified(
3✔
1741
        Validified(Yaml(parameters)): Validified<Yaml<ParametersValidify>>,
1742
    ) -> StatusCode {
1743
        check_validified(&parameters)
3✔
1744
    }
1745

1746
    pub async fn extract_yaml_validified_by_ref(
3✔
1747
        ValidifiedByRef(Yaml(parameters)): ValidifiedByRef<Yaml<ParametersValidify>>,
1748
    ) -> StatusCode {
1749
        check_validified(&parameters)
3✔
1750
    }
1751
}
1752

1753
#[cfg(feature = "msgpack")]
1754
mod msgpack {
1755
    use super::{check_modified, check_validated, check_validified, ParametersValidify};
1756
    use crate::{Modified, Validated, Validified, ValidifiedByRef};
1757
    use axum::http::StatusCode;
1758
    use axum_msgpack::{MsgPack, MsgPackRaw};
1759

1760
    pub mod route {
1761
        pub const MSGPACK: &str = "/msgpack";
1762
        pub const MSGPACK_MODIFIED: &str = "/msgpack_modified";
1763
        pub const MSGPACK_VALIDIFIED: &str = "/msgpack_validified";
1764
        pub const MSGPACK_VALIDIFIED_BY_REF: &str = "/msgpack_validified_by_ref";
1765
        pub const MSGPACK_RAW: &str = "/msgpack_raw";
1766
        pub const MSGPACK_RAW_MODIFIED: &str = "/msgpack_raw_modified";
1767
        pub const MSGPACK_RAW_VALIDIFIED: &str = "/msgpack_raw_validified";
1768
        pub const MSGPACK_RAW_VALIDIFIED_BY_REF: &str = "/msgpack_raw_validified_by_ref";
1769
    }
1770

1771
    pub async fn extract_msgpack(
3✔
1772
        Validated(MsgPack(parameters)): Validated<MsgPack<ParametersValidify>>,
1773
    ) -> StatusCode {
1774
        check_validated(&parameters)
3✔
1775
    }
1776

1777
    pub async fn extract_msgpack_modified(
3✔
1778
        Modified(MsgPack(parameters)): Modified<MsgPack<ParametersValidify>>,
1779
    ) -> StatusCode {
1780
        check_modified(&parameters)
3✔
1781
    }
1782

1783
    pub async fn extract_msgpack_validified(
3✔
1784
        Validified(MsgPack(parameters)): Validified<MsgPack<ParametersValidify>>,
1785
    ) -> StatusCode {
1786
        check_validified(&parameters)
3✔
1787
    }
1788

1789
    pub async fn extract_msgpack_validified_by_ref(
3✔
1790
        ValidifiedByRef(MsgPack(parameters)): ValidifiedByRef<MsgPack<ParametersValidify>>,
1791
    ) -> StatusCode {
1792
        check_validified(&parameters)
3✔
1793
    }
1794
    pub async fn extract_msgpack_raw(
3✔
1795
        Validated(MsgPackRaw(parameters)): Validated<MsgPackRaw<ParametersValidify>>,
1796
    ) -> StatusCode {
1797
        check_validated(&parameters)
3✔
1798
    }
1799

1800
    pub async fn extract_msgpack_raw_modified(
3✔
1801
        Modified(MsgPackRaw(parameters)): Modified<MsgPackRaw<ParametersValidify>>,
1802
    ) -> StatusCode {
1803
        check_modified(&parameters)
3✔
1804
    }
1805

1806
    pub async fn extract_msgpack_raw_validified(
3✔
1807
        Validified(MsgPackRaw(parameters)): Validified<MsgPackRaw<ParametersValidify>>,
1808
    ) -> StatusCode {
1809
        check_validified(&parameters)
3✔
1810
    }
1811

1812
    pub async fn extract_msgpack_raw_validified_by_ref(
3✔
1813
        ValidifiedByRef(MsgPackRaw(parameters)): ValidifiedByRef<MsgPackRaw<ParametersValidify>>,
1814
    ) -> StatusCode {
1815
        check_validified(&parameters)
3✔
1816
    }
1817
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc