Skip to content

Commit

Permalink
feat!: all structures should serialize correctly (#157)
Browse files Browse the repository at this point in the history
  • Loading branch information
cakekindel authored Jun 1, 2021
1 parent aedb5ae commit 8b44945
Show file tree
Hide file tree
Showing 55 changed files with 1,843 additions and 285 deletions.
69 changes: 69 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ mox = { version = "0.12", optional = true }
[dev-dependencies]
lazy_static = "1.4.0"
mox = "0.12"
pretty_assertions = "0.7.2"
4 changes: 2 additions & 2 deletions Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ dependencies = ["install-fmt"]

[tasks.doctest-slow]
command = "cargo"
args = ["--locked", "test", "--jobs", "1", "--doc", "--", "--quiet"]
args = ["--locked", "test", "--features", "xml", "--jobs", "1", "--doc", "--", "--quiet"]

[tasks.doctest]
command = "cargo"
args = ["--locked", "test", "--features", "xml", "--doc", "--", "--quiet"]

[tasks.test]
command = "cargo"
args = ["--locked", "test", "--tests", "--", "--quiet"]
args = ["--locked", "test", "--features", "xml", "--tests", "--", "--quiet"]
dependencies = ["doctest"]

[tasks.tdd]
Expand Down
11 changes: 11 additions & 0 deletions src/blocks/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,17 @@ pub mod build {
state: PhantomData::<_> }
}

/// Invoked by `blox!` when a child element is passed to `<actions_block>`.
///
/// Alias of `ActionsBuilder.element`.
pub fn child<El>(self,
element: El)
-> ActionsBuilder<'a, Set<method::elements>>
where El: Into<SupportedElement<'a>>
{
self.element(element)
}

/// Set `block_id` (Optional)
///
/// A string acting as a unique identifier for a block.
Expand Down
10 changes: 7 additions & 3 deletions src/blocks/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use std::borrow::Cow;
use serde::{Deserialize, Serialize};
use validator::Validate;

use crate::{convert, elems::Image, text, val_helpr::ValidationResult};
use crate::{convert,
elems::{BlockElement, Image},
text,
val_helpr::ValidationResult};

/// # Context Block
///
Expand Down Expand Up @@ -321,12 +324,13 @@ impl<'a> From<Vec<ImageOrText<'a>>> for Context<'a> {
/// The Composition objects supported by this block
#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
#[allow(missing_docs)]
#[serde(untagged)]
pub enum ImageOrText<'a> {
Text(text::Text),
Image(Image<'a>),
Image(BlockElement<'a>),
}

convert!(impl From<text::Text> for ImageOrText<'static> => |txt| ImageOrText::Text(txt));
convert!(impl<'a> From<Image<'a>> for ImageOrText<'a> => |i| ImageOrText::Image(i));
convert!(impl<'a> From<Image<'a>> for ImageOrText<'a> => |i| ImageOrText::Image(BlockElement::from(i)));
convert!(impl From<text::Plain> for ImageOrText<'static> => |t| text::Text::from(t).into());
convert!(impl From<text::Mrkdwn> for ImageOrText<'static> => |t| text::Text::from(t).into());
39 changes: 37 additions & 2 deletions src/blocks/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ impl<'a> Input<'a> {
}

/// Will allow the elements in this block to dispatch block_actions payloads. Defaults to false.
pub fn dispatch_block_actions(mut self) -> Self {
self.dispatch_action = Some(true);
pub fn dispatch_block_actions(mut self, should: bool) -> Self {
self.dispatch_action = Some(should);
self
}

Expand Down Expand Up @@ -345,6 +345,41 @@ pub mod build {
self.block_id = Some(block_id.into());
self
}

/// Set `dispatch_action` (Optional)
///
/// Will allow the elements in this block to
/// dispatch block_actions payloads.
///
/// Defaults to false.
pub fn dispatch_actions(mut self, should: bool) -> Self {
self.dispatch_action = Some(should);
self
}

/// Sets `optional` (**Required**)
///
/// A boolean that indicates whether the input
/// element may be empty when a user submits the modal.
///
/// Defaults to false.
pub fn optional(mut self, optional: bool) -> Self {
self.optional = Some(optional);
self
}

/// Set `hint` (Optional)
///
/// An optional hint that appears below an input element
/// in a lighter grey.
///
/// Maximum length for the text in this field is 2000 characters.
pub fn hint<T>(mut self, hint: T) -> Self
where T: Into<text::Plain>
{
self.hint = Some(hint.into().into());
self
}
}

impl<'a, L> InputBuilder<'a, RequiredMethodNotCalled<method::element>, L> {
Expand Down
97 changes: 60 additions & 37 deletions src/blocks/section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,14 +221,25 @@ pub mod build {
///
/// # Required Methods
/// `SectionBuilder::build()` is only available if these methods have been called:
/// - `element`
/// - `text` **or** `field(s)`, both may be called.
///
/// # Example
/// ```
/// use slack_blocks::{blocks::Section, elems::Image, text::ToSlackPlaintext};
/// use slack_blocks::{blocks::Section,
/// elems::Image,
/// text,
/// text::ToSlackPlaintext};
///
/// let block =
/// Section::builder().text("foo".plaintext())
/// .field("bar".plaintext())
/// .field("baz".plaintext())
/// // alternatively:
/// .fields(vec!["bar".plaintext(),
/// "baz".plaintext()]
/// .into_iter()
/// .map(text::Text::from)
/// )
/// .accessory(Image::builder().image_url("foo.png")
/// .alt_text("pic of foo")
/// .build())
Expand Down Expand Up @@ -261,72 +272,83 @@ pub mod build {
self
}

/// Add `text` (**Required**, can be called many times)
/// Add `text` (**Required: this or `field(s)`**)
///
/// One or many [text objects 🔗] to populate the block with.
///
/// # If called once:
/// Sets the `text` field of the section block.
/// The text for the block, in the form of a [text object 🔗].
///
/// Maximum length for the text in this field is 3000 characters.
///
/// # If called multiple times:
/// Sets the `fields` field of the section block.
/// [text object 🔗]: https://api.slack.com/reference/messaging/composition-objects#text
pub fn text<T>(self, text: T) -> SectionBuilder<'a, Set<method::text>>
where T: Into<text::Text>
{
SectionBuilder { accessory: self.accessory,
text: Some(text.into()),
fields: self.fields,
block_id: self.block_id,
state: PhantomData::<_> }
}

/// Set `fields` (**Required: this or `text`**)
///
/// A collection of [text objects 🔗].
///
/// Fields will be rendered in a compact format that allows for
/// Any text objects included with fields will be
/// rendered in a compact format that allows for
/// 2 columns of side-by-side text.
///
/// Maximum number of items is 10.
///
/// Maximum length for the text in each item is 2000 characters.
///
/// [text objects 🔗]: https://api.slack.com/reference/messaging/composition-objects#text
pub fn text<T>(self, text: T) -> SectionBuilder<'a, Set<method::text>>
where T: Into<text::Text>
pub fn fields<I>(self, fields: I) -> SectionBuilder<'a, Set<method::text>>
where I: IntoIterator<Item = text::Text>
{
let (text, fields) = match (self.text, self.fields) {
| (Some(t), None) => (None, Some(vec![t, text.into()])),
| (None, None) => (Some(text.into()), None),
| (None, Some(mut fs)) => {
fs.push(text.into());
(None, Some(fs))
},
| (Some(_), Some(_)) => {
unreachable!("fields and text should never both be set.")
},
};

SectionBuilder { accessory: self.accessory,
text,
fields,
text: self.text,
fields: Some(fields.into_iter().collect()),
block_id: self.block_id,
state: PhantomData::<_> }
}

/// Alias of `text` for XML macros, allowing fields
/// to be used as child elements.
/// Append a single field to `fields`.
pub fn field<T>(mut self, text: T) -> SectionBuilder<'a, Set<method::text>>
where T: Into<text::Text>
{
let mut fields = self.fields.take().unwrap_or_default();
fields.push(text.into());

self.fields(fields)
}

/// XML macro children, appends `fields` to the Section.
///
/// To set `text`, use the `text` attribute.
/// ```
/// use mox::mox;
/// use slack_blocks::{mox::*, text};
///
/// let as_attr = mox! {
/// <section_block text={text::Plain::from("Foo")} />
/// };
/// use slack_blocks::{blocks::Section, mox::*, text, text::ToSlackPlaintext};
///
/// let as_child = mox! {
/// <section_block>
/// let xml = mox! {
/// <section_block text={"Section".plaintext()}>
/// <text kind=plain>"Foo"</text>
/// <text kind=plain>"Bar"</text>
/// </section_block>
/// };
///
/// assert_eq!(as_attr, as_child);
/// let equiv = Section::builder().text("Section".plaintext())
/// .field("Foo".plaintext())
/// .field("Bar".plaintext())
/// .build();
///
/// assert_eq!(xml, equiv);
/// ```
#[cfg(feature = "xml")]
#[cfg_attr(docsrs, doc(cfg(feature = "xml")))]
pub fn child<T>(self, text: T) -> SectionBuilder<'a, Set<method::text>>
where T: Into<text::Text>
{
self.text(text)
self.field(text)
}

/// Set `block_id` (Optional)
Expand Down Expand Up @@ -381,6 +403,7 @@ pub mod build {
}
}
}

mod validate {
use super::*;
use crate::{compose::text,
Expand Down
2 changes: 2 additions & 0 deletions src/compose/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub struct Confirm {

#[validate(custom = "validate::deny")]
deny: text::Text,

#[serde(skip_serializing_if = "Option::is_none")]
style: Option<ConfirmStyle>,
}

Expand Down
5 changes: 5 additions & 0 deletions src/compose/conversation_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,13 @@ use crate::val_helpr::ValidationResult;
Validate)]
pub struct ConversationFilter {
#[validate(length(min = 1, max = 4))]
#[serde(skip_serializing_if = "Option::is_none")]
include: Option<Vec<ConversationKind>>,

#[serde(skip_serializing_if = "Option::is_none")]
exclude_external_shared_channels: Option<bool>,

#[serde(skip_serializing_if = "Option::is_none")]
exclude_bot_users: Option<bool>,
}

Expand Down
Loading

0 comments on commit 8b44945

Please sign in to comment.