Skip to content

Commit 651b1b7

Browse files
authored
feat!: move runtime validation to crate feature (#160)
* pain * more pain * :o * fmt * validation should dep on derive too * update comments
1 parent d40d1be commit 651b1b7

32 files changed

+368
-252
lines changed

Cargo.toml

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ categories = ["data-structures"]
1717
[features]
1818
unstable = ["blox", "validation"]
1919
blox = ["mox"]
20-
validation = []
20+
validation = ["validator", "validator_derive"]
2121

2222
[package.metadata.docs.rs]
2323
all-features = true
@@ -28,12 +28,12 @@ maintenance = { status = "actively-developed" }
2828

2929
[dependencies]
3030
serde = { version = "^1", features = ["derive"] }
31-
serde_json = "^1"
32-
validator = "0.10.0"
33-
validator_derive = "0.10.0"
31+
validator = { version = "0.10.0", optional = true }
32+
validator_derive = { version = "0.10.0", optional = true }
3433
mox = { version = "0.12", optional = true }
3534

3635
[dev-dependencies]
36+
serde_json = "^1"
3737
lazy_static = "1.4.0"
3838
mox = "0.12"
3939
pretty_assertions = "0.7.2"

src/blocks/actions.rs

+13-16
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
use std::{borrow::Cow, convert::TryFrom};
1111

1212
use serde::{Deserialize, Serialize};
13+
#[cfg(feature = "validation")]
1314
use validator::Validate;
1415

16+
#[cfg(feature = "validation")]
17+
use crate::val_helpr::*;
1518
use crate::{convert,
1619
elems::{select,
1720
BlockElement,
@@ -20,8 +23,7 @@ use crate::{convert,
2023
DatePicker,
2124
Overflow,
2225
Radio,
23-
TextInput},
24-
val_helpr::*};
26+
TextInput}};
2527

2628
/// # Actions Block
2729
///
@@ -31,20 +33,15 @@ use crate::{convert,
3133
///
3234
/// [slack api docs 🔗]: https://api.slack.com/reference/block-kit/blocks#actions
3335
/// [elements 🔗]: https://api.slack.com/reference/messaging/block-elements
34-
#[derive(Clone,
35-
Debug,
36-
Default,
37-
Deserialize,
38-
Hash,
39-
PartialEq,
40-
Serialize,
41-
Validate)]
36+
#[derive(Clone, Debug, Default, Deserialize, Hash, PartialEq, Serialize)]
37+
#[cfg_attr(feature = "validation", derive(Validate))]
4238
pub struct Actions<'a> {
43-
#[validate(length(max = 5))]
39+
#[cfg_attr(feature = "validation", validate(length(max = 5)))]
4440
elements: Vec<SupportedElement<'a>>,
4541

4642
#[serde(skip_serializing_if = "Option::is_none")]
47-
#[validate(custom = "super::validate_block_id")]
43+
#[cfg_attr(feature = "validation",
44+
validate(custom = "super::validate_block_id"))]
4845
block_id: Option<Cow<'a, str>>,
4946
}
5047

@@ -59,10 +56,8 @@ impl<'a> Actions<'a> {
5956
/// Validate that this Section block agrees with Slack's model requirements
6057
///
6158
/// # Errors
62-
/// - If `with_block_id` was called with a block id longer
63-
/// than 255 chars
64-
/// - If `from_elements` or `from_action_elements` was
65-
/// called with more than 5 elements.
59+
/// - If `block_id` longer than 255 chars
60+
/// - If `elements` contains more than 5 elements
6661
///
6762
/// # Example
6863
/// ```
@@ -79,6 +74,8 @@ impl<'a> Actions<'a> {
7974
///
8075
/// assert!(matches!(block.validate(), Err(_)));
8176
/// ```
77+
#[cfg(feature = "validation")]
78+
#[cfg_attr(docsrs, doc(cfg(feature = "validation")))]
8279
pub fn validate(&self) -> ValidationResult {
8380
Validate::validate(self)
8481
}

src/blocks/context.rs

+13-16
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
use std::borrow::Cow;
1010

1111
use serde::{Deserialize, Serialize};
12+
#[cfg(feature = "validation")]
1213
use validator::Validate;
1314

15+
#[cfg(feature = "validation")]
16+
use crate::val_helpr::ValidationResult;
1417
use crate::{convert,
1518
elems::{BlockElement, Image},
16-
text,
17-
val_helpr::ValidationResult};
19+
text};
1820

1921
/// # Context Block
2022
///
@@ -23,20 +25,15 @@ use crate::{convert,
2325
/// Displays message context, which can include both images and text.
2426
///
2527
/// [context_docs]: https://api.slack.com/reference/block-kit/blocks#context
26-
#[derive(Clone,
27-
Debug,
28-
Default,
29-
Deserialize,
30-
Hash,
31-
PartialEq,
32-
Serialize,
33-
Validate)]
28+
#[derive(Clone, Debug, Default, Deserialize, Hash, PartialEq, Serialize)]
29+
#[cfg_attr(feature = "validation", derive(Validate))]
3430
pub struct Context<'a> {
35-
#[validate(length(max = 10))]
31+
#[cfg_attr(feature = "validation", validate(length(max = 10)))]
3632
elements: Vec<ImageOrText<'a>>,
3733

3834
#[serde(skip_serializing_if = "Option::is_none")]
39-
#[validate(custom = "super::validate_block_id")]
35+
#[cfg_attr(feature = "validation",
36+
validate(custom = "super::validate_block_id"))]
4037
block_id: Option<Cow<'a, str>>,
4138
}
4239

@@ -51,10 +48,8 @@ impl<'a> Context<'a> {
5148
/// Validate that this Context block agrees with Slack's model requirements
5249
///
5350
/// # Errors
54-
/// - If `with_block_id` was called with a block id longer
55-
/// than 255 chars
56-
/// - If `from_elements`, `from_context_elements`, or `with_element` was called with
57-
/// more than 10 objects
51+
/// - If `block_id` longer than 255 chars
52+
/// - If `elements` contains more than 10 objects
5853
///
5954
/// # Example
6055
/// ```
@@ -68,6 +63,8 @@ impl<'a> Context<'a> {
6863
///
6964
/// assert_eq!(true, matches!(block.validate(), Err(_)));
7065
/// ```
66+
#[cfg(feature = "validation")]
67+
#[cfg_attr(docsrs, doc(cfg(feature = "validation")))]
7168
pub fn validate(&self) -> ValidationResult {
7269
Validate::validate(self)
7370
}

src/blocks/file.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
use std::borrow::Cow;
1111

1212
use serde::{Deserialize, Serialize};
13+
#[cfg(feature = "validation")]
1314
use validator::Validate;
1415

16+
#[cfg(feature = "validation")]
1517
use crate::val_helpr::ValidationResult;
1618

1719
/// # File Block
@@ -22,12 +24,15 @@ use crate::val_helpr::ValidationResult;
2224
///
2325
/// [slack api docs 🔗]: https://api.slack.com/reference/block-kit/blocks#file
2426
/// [remote file 🔗]: https://api.slack.com/messaging/files/remote
25-
#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize, Validate)]
27+
#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
28+
#[cfg_attr(feature = "validation", derive(Validate))]
2629
pub struct File<'a> {
2730
external_id: Cow<'a, str>,
2831
source: Cow<'a, str>,
32+
2933
#[serde(skip_serializing_if = "Option::is_none")]
30-
#[validate(custom = "super::validate_block_id")]
34+
#[cfg_attr(feature = "validation",
35+
validate(custom = "super::validate_block_id"))]
3136
block_id: Option<Cow<'a, str>>,
3237
}
3338

@@ -42,8 +47,7 @@ impl<'a> File<'a> {
4247
/// Validate that this File block agrees with Slack's model requirements
4348
///
4449
/// # Errors
45-
/// - If `with_block_id` was called with a block id longer
46-
/// than 256 chars
50+
/// - If `block_id` longer than 256 chars
4751
///
4852
/// # Example
4953
/// ```
@@ -63,6 +67,8 @@ impl<'a> File<'a> {
6367
/// # Ok(())
6468
/// # }
6569
/// ```
70+
#[cfg(feature = "validation")]
71+
#[cfg_attr(docsrs, doc(cfg(feature = "validation")))]
6672
pub fn validate(&self) -> ValidationResult {
6773
Validate::validate(self)
6874
}

src/blocks/image.rs

+18-20
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
use std::borrow::Cow;
1010

1111
use serde::{Deserialize, Serialize};
12+
#[cfg(feature = "validation")]
1213
use validator::Validate;
1314

14-
use crate::{compose::text, val_helpr::ValidationResult};
15+
use crate::compose::text;
16+
#[cfg(feature = "validation")]
17+
use crate::val_helpr::ValidationResult;
1518

1619
/// # Image Block
1720
///
@@ -20,27 +23,22 @@ use crate::{compose::text, val_helpr::ValidationResult};
2023
/// A simple image block, designed to make those cat photos really pop.
2124
///
2225
/// [slack api docs 🔗]: https://api.slack.com/reference/block-kit/blocks#image
23-
#[derive(Clone,
24-
Debug,
25-
Default,
26-
Deserialize,
27-
Hash,
28-
PartialEq,
29-
Serialize,
30-
Validate)]
26+
#[derive(Clone, Debug, Default, Deserialize, Hash, PartialEq, Serialize)]
27+
#[cfg_attr(feature = "validation", derive(Validate))]
3128
pub struct Image<'a> {
32-
#[validate(length(max = 3000))]
29+
#[cfg_attr(feature = "validation", validate(length(max = 3000)))]
3330
image_url: Cow<'a, str>,
3431

35-
#[validate(length(max = 2000))]
32+
#[cfg_attr(feature = "validation", validate(length(max = 2000)))]
3633
alt_text: Cow<'a, str>,
3734

3835
#[serde(skip_serializing_if = "Option::is_none")]
39-
#[validate(custom = "validate::title")]
36+
#[cfg_attr(feature = "validation", validate(custom = "validate::title"))]
4037
title: Option<text::Text>,
4138

4239
#[serde(skip_serializing_if = "Option::is_none")]
43-
#[validate(custom = "super::validate_block_id")]
40+
#[cfg_attr(feature = "validation",
41+
validate(custom = "super::validate_block_id"))]
4442
block_id: Option<Cow<'a, str>>,
4543
}
4644

@@ -55,14 +53,11 @@ impl<'a> Image<'a> {
5553
/// Validate that this Image block agrees with Slack's model requirements
5654
///
5755
/// # Errors
58-
/// - If `with_block_id` was called with a block id longer
56+
/// - If `block_id` longer
5957
/// than 255 chars
60-
/// - If `with_title` was called with a title longer
61-
/// than 2000 chars
62-
/// - If `from_url_and_alt_text` was called with `alt_text` longer
63-
/// than 2000 chars
64-
/// - If `from_url_and_alt_text` was called with `image_url` longer
65-
/// than 3000 chars
58+
/// - If title longer than 2000 chars
59+
/// - If `alt_text` longer than 2000 chars
60+
/// - If `image_url` longer than 3000 chars
6661
///
6762
/// # Example
6863
/// ```
@@ -77,6 +72,8 @@ impl<'a> Image<'a> {
7772
///
7873
/// assert_eq!(true, matches!(block.validate(), Err(_)));
7974
/// ```
75+
#[cfg(feature = "validation")]
76+
#[cfg_attr(docsrs, doc(cfg(feature = "validation")))]
8077
pub fn validate(&self) -> ValidationResult {
8178
Validate::validate(self)
8279
}
@@ -257,6 +254,7 @@ pub mod build {
257254
}
258255
}
259256

257+
#[cfg(feature = "validation")]
260258
mod validate {
261259
use crate::{compose::text,
262260
val_helpr::{below_len, ValidatorResult}};

src/blocks/input.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
use std::borrow::Cow;
1414

1515
use serde::{Deserialize, Serialize};
16+
#[cfg(feature = "validation")]
1617
use validator::Validate;
1718

19+
#[cfg(feature = "validation")]
20+
use crate::val_helpr::ValidationResult;
1821
use crate::{compose::text,
1922
convert,
2023
elems,
21-
elems::{select, BlockElement},
22-
val_helpr::ValidationResult};
24+
elems::{select, BlockElement}};
2325

2426
/// # Input Block
2527
///
@@ -32,19 +34,21 @@ use crate::{compose::text,
3234
///
3335
/// [slack api docs 🔗]: https://api.slack.com/reference/block-kit/blocks#input
3436
/// [slack's guide to using modals 🔗]: https://api.slack.com/surfaces/modals/using#gathering_input
35-
#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize, Validate)]
37+
#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
38+
#[cfg_attr(feature = "validation", derive(Validate))]
3639
pub struct Input<'a> {
37-
#[validate(custom = "validate::label")]
40+
#[cfg_attr(feature = "validation", validate(custom = "validate::label"))]
3841
label: text::Text,
3942

4043
element: SupportedElement<'a>,
4144

4245
#[serde(skip_serializing_if = "Option::is_none")]
43-
#[validate(custom = "super::validate_block_id")]
46+
#[cfg_attr(feature = "validation",
47+
validate(custom = "super::validate_block_id"))]
4448
block_id: Option<Cow<'a, str>>,
4549

4650
#[serde(skip_serializing_if = "Option::is_none")]
47-
#[validate(custom = "validate::hint")]
51+
#[cfg_attr(feature = "validation", validate(custom = "validate::hint"))]
4852
hint: Option<text::Text>,
4953

5054
#[serde(skip_serializing_if = "Option::is_none")]
@@ -67,10 +71,8 @@ impl<'a> Input<'a> {
6771
/// # Errors
6872
/// - If `from_label_and_element` was passed a Text object longer
6973
/// than 2000 chars
70-
/// - If `with_hint` was called with a block id longer
71-
/// than 2000 chars
72-
/// - If `with_block_id` was called with a block id longer
73-
/// than 256 chars
74+
/// - If `hint` longer than 2000 chars
75+
/// - If `block_id` longer than 256 chars
7476
///
7577
/// # Example
7678
/// ```
@@ -94,6 +96,8 @@ impl<'a> Input<'a> {
9496
///
9597
/// // < send to slack API >
9698
/// ```
99+
#[cfg(feature = "validation")]
100+
#[cfg_attr(docsrs, doc(cfg(feature = "validation")))]
97101
pub fn validate(&self) -> ValidationResult {
98102
Validate::validate(self)
99103
}
@@ -338,6 +342,7 @@ convert!(impl<'a> From<select::multi::User<'a>> for SupportedElement<'a> => |r|
338342
convert!(impl<'a> From<select::multi::Conversation<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
339343
convert!(impl<'a> From<select::multi::PublicChannel<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
340344

345+
#[cfg(feature = "validation")]
341346
mod validate {
342347
use crate::{compose::text,
343348
val_helpr::{below_len, ValidatorResult}};

src/blocks/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ pub mod section;
4545
#[doc(inline)]
4646
pub use section::Section;
4747

48-
type ValidationResult = Result<(), validator::ValidationErrors>;
49-
5048
/// # Layout Blocks
5149
///
5250
/// Blocks are a series of components that can be combined
@@ -119,6 +117,8 @@ impl<'a> Block<'a> {
119117
///
120118
/// assert!(matches!(img.validate(), Err(_)), "validation should fail!")
121119
/// ```
120+
#[cfg(feature = "validation")]
121+
#[cfg_attr(docsrs, doc(cfg(feature = "validation")))]
122122
pub fn validate(&self) -> ValidationResult {
123123
use Block::*;
124124

@@ -141,6 +141,7 @@ convert!(impl<'a> From<Image<'a>> for Block<'a> => |a| Block::Image(a));
141141
convert!(impl<'a> From<Context<'a>> for Block<'a> => |a| Block::Context(a));
142142
convert!(impl<'a> From<File<'a>> for Block<'a> => |a| Block::File(a));
143143

144+
#[cfg(feature = "validation")]
144145
fn validate_block_id(id: &std::borrow::Cow<str>)
145146
-> crate::val_helpr::ValidatorResult {
146147
crate::val_helpr::below_len("block_id", 255, id)

0 commit comments

Comments
 (0)