Skip to content

Commit

Permalink
Switch away from custom TryFrom/Into traits
Browse files Browse the repository at this point in the history
  • Loading branch information
CosmicHorrorDev committed Nov 13, 2021
1 parent d74be07 commit c5ffb92
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 86 deletions.
5 changes: 3 additions & 2 deletions src/attachment.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::error::{Error, Result};
use crate::{HexColor, SlackText, SlackTime, TryInto};
use crate::{HexColor, SlackText, SlackTime};
use chrono::NaiveDateTime;
use reqwest::Url;
use serde::Serialize;
use std::convert::TryInto;

/// Slack allows for attachments to be added to messages. See
/// https://api.slack.com/docs/attachments for more information.
Expand Down Expand Up @@ -193,7 +194,7 @@ impl AttachmentBuilder {
/// 3. Any valid hex color code: e.g. `#b13d41` or `#000`.
///
/// hex color codes will be checked to ensure a valid hex number is provided
pub fn color<C: TryInto<HexColor, Err = Error>>(self, color: C) -> AttachmentBuilder {
pub fn color<C: TryInto<HexColor, Error = Error>>(self, color: C) -> AttachmentBuilder {
match self.inner {
Ok(mut inner) => match color.try_into() {
Ok(c) => {
Expand Down
45 changes: 22 additions & 23 deletions src/hexx.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::error::{Error, ErrorKind};
use crate::TryFrom;
use std::{convert::TryFrom, str::FromStr};

use hex::FromHex;
use serde::Serialize;
Expand Down Expand Up @@ -30,6 +30,14 @@ impl ::std::fmt::Display for HexColor {
}
}

impl TryFrom<&str> for HexColor {
type Error = Error;

fn try_from(s: &str) -> Result<Self, Self::Error> {
s.parse()
}
}

/// Default slack colors built-in to the API
/// See: https://api.slack.com/docs/attachments
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -66,12 +74,10 @@ impl From<SlackColor> for HexColor {
}
}

impl<S> TryFrom<S> for HexColor
where
S: Into<String>,
{
impl FromStr for HexColor {
type Err = Error;
fn try_from(s: S) -> ::std::result::Result<Self, Self::Err> {

fn from_str(s: &str) -> Result<Self, Self::Err> {
let s: String = s.into();
if SLACK_COLORS.contains(&&s[..]) {
return Ok(HexColor(s));
Expand Down Expand Up @@ -109,22 +115,15 @@ where
}
}

// even though this will always succeed, it simplifies the trait bound in the builder
impl TryFrom<SlackColor> for HexColor {
type Err = Error;
fn try_from(color: SlackColor) -> ::std::result::Result<Self, Self::Err> {
Ok(color.into())
}
}

#[cfg(test)]
mod test {
use super::*;
use crate::{HexColor, TryFrom};
use crate::HexColor;
use std::convert::TryFrom;

#[test]
fn test_hex_color_too_short() {
let err = HexColor::try_from("abc").unwrap_err();
let err = HexColor::from_str("abc").unwrap_err();
assert_eq!(
err.to_string(),
"hex color parsing error: Must be 4 or 7 characters long (including #): found \
Expand All @@ -134,7 +133,7 @@ mod test {

#[test]
fn test_hex_color_missing_hash() {
let err = HexColor::try_from("1234567").unwrap_err();
let err = HexColor::from_str("1234567").unwrap_err();
assert_eq!(
err.to_string(),
"hex color parsing error: No leading #: found `1234567`"
Expand All @@ -143,39 +142,39 @@ mod test {

#[test]
fn test_hex_color_invalid_hex_fmt() {
let err = HexColor::try_from("#abc12z").unwrap_err();
let err = HexColor::from_str("#abc12z").unwrap_err();
assert!(err
.to_string()
.contains("Invalid character 'z' at position 5"));
}

#[test]
fn test_hex_color_good() {
let h: HexColor = HexColor::try_from(SlackColor::Good).unwrap();
let h: HexColor = HexColor::from_str(&SlackColor::Good.to_string()).unwrap();
assert_eq!(h.to_string(), "good");
}

#[test]
fn test_hex_color_danger_str() {
let ok = HexColor::try_from("danger").unwrap();
let ok = HexColor::from_str("danger").unwrap();
assert_eq!(ok.to_string(), "danger");
}

#[test]
fn test_hex_color_3_char_hex() {
let ok = HexColor::try_from("#d18").unwrap();
let ok = HexColor::from_str("#d18").unwrap();
assert_eq!(ok.to_string(), "#d18");
}

#[test]
fn test_hex_color_valid_upper_hex() {
let ok = HexColor::try_from("#103D18").unwrap();
let ok = HexColor::from_str("#103D18").unwrap();
assert_eq!(ok.to_string(), "#103D18");
}

#[test]
fn test_hex_color_valid_lower_hex() {
let ok = HexColor::try_from("#103d18").unwrap();
let ok = HexColor::from_str("#103d18").unwrap();
assert_eq!(ok.to_string(), "#103d18");
}
}
54 changes: 2 additions & 52 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
unstable_features,
unused_import_braces,
unused_qualifications,
unused_results
unused_results,
rust_2018_idioms
)]
#![warn(rust_2018_idioms)]

//! Library to send messages to slack rooms
//! supports entire messaging API, including attachments and fields
Expand All @@ -32,53 +32,3 @@ mod error;
mod hexx;
mod payload;
mod slack;

/// Waiting to stabilize: https://github.com/rust-lang/rust/issues/33417
///
/// An attempted conversion that consumes `self`, which may or may not be expensive.
///
/// Library authors should not directly implement this trait, but should prefer implementing
/// the [`TryFrom`] trait, which offers greater flexibility and provides an equivalent `TryInto`
/// implementation for free, thanks to a blanket implementation in the standard library.
///
/// [`TryFrom`]: trait.TryFrom.html
pub trait TryInto<T>: Sized {
/// The type returned in the event of a conversion error.
type Err;

/// Performs the conversion.
fn try_into(self) -> ::std::result::Result<T, Self::Err>;
}

/// Waiting to stabilize: https://github.com/rust-lang/rust/issues/33417
///
/// Attempt to construct `Self` via a conversion.
pub trait TryFrom<T>: Sized {
/// The type returned in the event of a conversion error.
type Err;

/// Performs the conversion.
fn try_from(_: T) -> ::std::result::Result<Self, Self::Err>;
}

impl<T, U> TryInto<U> for T
where
U: TryFrom<T>,
{
type Err = U::Err;

fn try_into(self) -> ::std::result::Result<U, U::Err> {
U::try_from(self)
}
}

impl<'a> TryFrom<&'a str> for reqwest::Url {
type Err = Error;

fn try_from(s: &str) -> ::std::result::Result<Self, Self::Err> {
match s.parse() {
Ok(u) => Ok(u),
Err(e) => Err(e.into()),
}
}
}
6 changes: 3 additions & 3 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ macro_rules! url_builder_fn {
$name:ident, $builder:ident
} => {
$(#[$meta])+
pub fn $name<U: TryInto<::reqwest::Url, Err = Error>>(self, $name: U) -> $builder {
pub fn $name(self, $name: &str) -> $builder {
match self.inner {
Ok(mut inner) => {
match $name.try_into() {
match Url::parse($name) {
Ok(url) => {
inner.$name = Some(url);
$builder { inner: Ok(inner) }
}
Err(e) => $builder { inner: Err(e) },
Err(e) => $builder { inner: Err(e.into()) },
}
}
_ => self,
Expand Down
4 changes: 2 additions & 2 deletions src/payload.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::error::{Error, Result};
use crate::{Attachment, SlackText, TryInto};
use crate::error::Result;
use crate::{Attachment, SlackText};
use reqwest::Url;
use serde::{Serialize, Serializer};

Expand Down
8 changes: 4 additions & 4 deletions src/slack.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::error::{Error, ErrorKind, Result};
use crate::{Payload, TryInto};
use crate::error::{ErrorKind, Result};
use crate::Payload;
use chrono::NaiveDateTime;
use reqwest::{Client, Url};
use serde::{Serialize, Serializer};
Expand All @@ -14,9 +14,9 @@ pub struct Slack {

impl Slack {
/// Construct a new instance of slack for a specific incoming url endpoint.
pub fn new<T: TryInto<Url, Err = Error>>(hook: T) -> Result<Slack> {
pub fn new<T: reqwest::IntoUrl>(hook: T) -> Result<Slack> {
Ok(Slack {
hook: hook.try_into()?,
hook: hook.into_url()?,
client: Client::new(),
})
}
Expand Down

0 comments on commit c5ffb92

Please sign in to comment.