diff --git a/.travis.yml b/.travis.yml index 7d848609..129d203c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,5 +32,6 @@ script: cargo clippy --all-targets --all-features -- -D warnings fi - cargo build --verbose - - cargo test --verbose + - cargo test --no-default-features --verbose + - cargo test --all-features --verbose if: "type != push OR (tag IS blank AND branch = master)" diff --git a/CHANGELOG.md b/CHANGELOG.md index e9e40bc5..07fe41d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,10 +19,14 @@ Breaking changes: instead of `&url::Host` * `Error::InvalidHost` has been renamed to `Error::InvalidServerName`, because it also covers errors in the port, not just the host part section of the server name +* The random identifier generation functions (`Id::new`) are now only available if the `rand` + feature of this crate is enabled Improvements: * Add support for historical uppercase MXIDs +* Made all dependencies optional + * `serde` is the only one that is enabled by default # 0.14.1 diff --git a/Cargo.toml b/Cargo.toml index 34d31961..bcaf4d11 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,10 +12,13 @@ repository = "https://github.com/ruma/ruma-identifiers" version = "0.14.1" edition = "2018" +[features] +default = ["serde"] + [dependencies] diesel = { version = "1.4.4", optional = true } -rand = "0.7.3" -serde = "1.0.106" +rand = { version = "0.7.3", optional = true } +serde = { version = "1.0.106", optional = true } [dev-dependencies] serde_json = "1.0.51" diff --git a/src/device_id.rs b/src/device_id.rs index 549ec2cc..8ee95378 100644 --- a/src/device_id.rs +++ b/src/device_id.rs @@ -1,5 +1,6 @@ //! Matrix device identifiers. +#[cfg(feature = "rand")] use crate::generate_localpart; /// A Matrix device ID. @@ -9,11 +10,12 @@ use crate::generate_localpart; pub type DeviceId = String; /// Generates a random `DeviceId`, suitable for assignment to a new device. +#[cfg(feature = "rand")] pub fn generate() -> DeviceId { generate_localpart(8) } -#[cfg(test)] +#[cfg(all(test, feature = "rand"))] mod tests { use super::generate; diff --git a/src/event_id.rs b/src/event_id.rs index 40b1ef37..b93688d6 100644 --- a/src/event_id.rs +++ b/src/event_id.rs @@ -5,7 +5,7 @@ use std::{borrow::Cow, convert::TryFrom, num::NonZeroU8}; #[cfg(feature = "diesel")] use diesel::sql_types::Text; -use crate::{error::Error, generate_localpart, is_valid_server_name, parse_id, validate_id}; +use crate::{error::Error, parse_id, validate_id}; /// A Matrix event ID. /// @@ -55,7 +55,10 @@ impl EventId { /// /// Does not currently ever fail, but may fail in the future if the homeserver cannot be parsed /// parsed as a valid host. + #[cfg(feature = "rand")] pub fn new(server_name: &str) -> Result { + use crate::{generate_localpart, is_valid_server_name}; + if !is_valid_server_name(server_name) { return Err(Error::InvalidServerName); } @@ -121,6 +124,7 @@ common_impls!(EventId, "a Matrix event ID"); mod tests { use std::convert::TryFrom; + #[cfg(feature = "serde")] use serde_json::{from_str, to_string}; use super::EventId; @@ -156,6 +160,7 @@ mod tests { ) } + #[cfg(feature = "rand")] #[test] fn generate_random_valid_event_id() { let event_id = EventId::new("example.com").expect("Failed to generate EventId."); @@ -165,11 +170,13 @@ mod tests { assert_eq!(id_str.len(), 31); } + #[cfg(feature = "rand")] #[test] fn generate_random_invalid_event_id() { assert!(EventId::new("").is_err()); } + #[cfg(feature = "serde")] #[test] fn serialize_valid_original_event_id() { assert_eq!( @@ -181,6 +188,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn serialize_valid_base64_event_id() { assert_eq!( @@ -193,6 +201,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn serialize_valid_url_safe_base64_event_id() { assert_eq!( @@ -205,6 +214,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn deserialize_valid_original_event_id() { assert_eq!( @@ -214,6 +224,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn deserialize_valid_base64_event_id() { assert_eq!( @@ -224,6 +235,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn deserialize_valid_url_safe_base64_event_id() { assert_eq!( diff --git a/src/lib.rs b/src/lib.rs index 45bcf63d..8ea4364e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,9 +14,9 @@ #[cfg_attr(feature = "diesel", macro_use)] extern crate diesel; -use std::{borrow::Cow, convert::TryFrom, num::NonZeroU8}; +use std::num::NonZeroU8; -use rand::{distributions::Alphanumeric, thread_rng, Rng}; +#[cfg(feature = "serde")] use serde::de::{self, Deserialize as _, Deserializer, Unexpected}; #[doc(inline)] @@ -51,9 +51,11 @@ const MAX_BYTES: usize = 255; const MIN_CHARS: usize = 4; /// Generates a random identifier localpart. +#[cfg(feature = "rand")] fn generate_localpart(length: usize) -> String { - thread_rng() - .sample_iter(&Alphanumeric) + use rand::Rng as _; + rand::thread_rng() + .sample_iter(&rand::distributions::Alphanumeric) .take(length) .collect() } @@ -95,12 +97,13 @@ fn parse_id(id: &str, valid_sigils: &[char]) -> Result { /// Deserializes any type of id using the provided TryFrom implementation. /// /// This is a helper function to reduce the boilerplate of the Deserialize implementations. +#[cfg(feature = "serde")] fn deserialize_id<'de, D, T>(deserializer: D, expected_str: &str) -> Result where D: Deserializer<'de>, - T: for<'a> TryFrom<&'a str>, + T: for<'a> std::convert::TryFrom<&'a str>, { - Cow::<'_, str>::deserialize(deserializer).and_then(|v| { + std::borrow::Cow::<'_, str>::deserialize(deserializer).and_then(|v| { T::try_from(&v).map_err(|_| de::Error::invalid_value(Unexpected::Str(&v), &expected_str)) }) } diff --git a/src/macros.rs b/src/macros.rs index 8daf46f1..b823ff20 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -63,6 +63,7 @@ macro_rules! common_impls { } } + #[cfg(feature = "serde")] impl ::serde::Serialize for $id { fn serialize(&self, serializer: S) -> Result where @@ -72,6 +73,7 @@ macro_rules! common_impls { } } + #[cfg(feature = "serde")] impl<'de> ::serde::Deserialize<'de> for $id { fn deserialize(deserializer: D) -> Result where diff --git a/src/room_alias_id.rs b/src/room_alias_id.rs index 6bf23924..2649621b 100644 --- a/src/room_alias_id.rs +++ b/src/room_alias_id.rs @@ -62,6 +62,7 @@ common_impls!(RoomAliasId, "a Matrix room alias ID"); mod tests { use std::convert::TryFrom; + #[cfg(feature = "serde")] use serde_json::{from_str, to_string}; use super::RoomAliasId; @@ -77,6 +78,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn serialize_valid_room_alias_id() { assert_eq!( @@ -88,6 +90,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn deserialize_valid_room_alias_id() { assert_eq!( diff --git a/src/room_id.rs b/src/room_id.rs index 9505ac3e..9d2ae762 100644 --- a/src/room_id.rs +++ b/src/room_id.rs @@ -5,7 +5,7 @@ use std::{borrow::Cow, convert::TryFrom, num::NonZeroU8}; #[cfg(feature = "diesel")] use diesel::sql_types::Text; -use crate::{error::Error, generate_localpart, is_valid_server_name, parse_id}; +use crate::{error::Error, parse_id}; /// A Matrix room ID. /// @@ -33,7 +33,10 @@ impl RoomId { /// 18 random ASCII characters. /// /// Fails if the given homeserver cannot be parsed as a valid host. + #[cfg(feature = "rand")] pub fn new(server_name: &str) -> Result { + use crate::{generate_localpart, is_valid_server_name}; + if !is_valid_server_name(server_name) { return Err(Error::InvalidServerName); } @@ -79,6 +82,7 @@ common_impls!(RoomId, "a Matrix room ID"); mod tests { use std::convert::TryFrom; + #[cfg(feature = "serde")] use serde_json::{from_str, to_string}; use super::RoomId; @@ -94,6 +98,7 @@ mod tests { ); } + #[cfg(feature = "rand")] #[test] fn generate_random_valid_room_id() { let room_id = RoomId::new("example.com").expect("Failed to generate RoomId."); @@ -103,11 +108,13 @@ mod tests { assert_eq!(id_str.len(), 31); } + #[cfg(feature = "rand")] #[test] fn generate_random_invalid_room_id() { assert!(RoomId::new("").is_err()); } + #[cfg(feature = "serde")] #[test] fn serialize_valid_room_id() { assert_eq!( @@ -119,6 +126,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn deserialize_valid_room_id() { assert_eq!( diff --git a/src/room_id_or_room_alias_id.rs b/src/room_id_or_room_alias_id.rs index 9023824c..fe7ab364 100644 --- a/src/room_id_or_room_alias_id.rs +++ b/src/room_id_or_room_alias_id.rs @@ -93,6 +93,7 @@ common_impls!(RoomIdOrAliasId, "a Matrix room ID or room alias ID"); mod tests { use std::convert::TryFrom; + #[cfg(feature = "serde")] use serde_json::{from_str, to_string}; use super::RoomIdOrAliasId; @@ -126,6 +127,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn serialize_valid_room_id_or_alias_id_with_a_room_alias_id() { assert_eq!( @@ -138,6 +140,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn serialize_valid_room_id_or_alias_id_with_a_room_id() { assert_eq!( @@ -150,6 +153,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn deserialize_valid_room_id_or_alias_id_with_a_room_alias_id() { assert_eq!( @@ -159,6 +163,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn deserialize_valid_room_id_or_alias_id_with_a_room_id() { assert_eq!( diff --git a/src/room_version_id.rs b/src/room_version_id.rs index 5e8d8d35..603a5085 100644 --- a/src/room_version_id.rs +++ b/src/room_version_id.rs @@ -8,9 +8,10 @@ use std::{ #[cfg(feature = "diesel")] use diesel::sql_types::Text; +#[cfg(feature = "serde")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use crate::{deserialize_id, error::Error}; +use crate::error::Error; /// Room version identifiers cannot be more than 32 code points. const MAX_CODE_POINTS: usize = 32; @@ -155,6 +156,7 @@ impl Display for RoomVersionId { } } +#[cfg(feature = "serde")] impl Serialize for RoomVersionId { fn serialize(&self, serializer: S) -> Result where @@ -164,12 +166,13 @@ impl Serialize for RoomVersionId { } } +#[cfg(feature = "serde")] impl<'de> Deserialize<'de> for RoomVersionId { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { - deserialize_id(deserializer, "a Matrix room version ID as a string") + crate::deserialize_id(deserializer, "a Matrix room version ID as a string") } } @@ -243,6 +246,7 @@ impl PartialEq for String { mod tests { use std::convert::TryFrom; + #[cfg(feature = "serde")] use serde_json::{from_str, to_string}; use super::RoomVersionId; @@ -324,6 +328,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn serialize_official_room_id() { assert_eq!( @@ -333,6 +338,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn deserialize_official_room_id() { let deserialized = @@ -347,6 +353,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn serialize_custom_room_id() { assert_eq!( @@ -358,6 +365,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn deserialize_custom_room_id() { let deserialized = from_str::(r#""io.ruma.1""#) diff --git a/src/user_id.rs b/src/user_id.rs index 63532ccb..31a67100 100644 --- a/src/user_id.rs +++ b/src/user_id.rs @@ -5,7 +5,7 @@ use std::{borrow::Cow, convert::TryFrom, num::NonZeroU8}; #[cfg(feature = "diesel")] use diesel::sql_types::Text; -use crate::{error::Error, generate_localpart, is_valid_server_name, parse_id}; +use crate::{error::Error, parse_id}; /// A Matrix user ID. /// @@ -39,7 +39,10 @@ impl UserId { /// 12 random ASCII characters. /// /// Fails if the given homeserver cannot be parsed as a valid host. + #[cfg(feature = "rand")] pub fn new(server_name: &str) -> Result { + use crate::{generate_localpart, is_valid_server_name}; + if !is_valid_server_name(server_name) { return Err(Error::InvalidServerName); } @@ -108,6 +111,7 @@ common_impls!(UserId, "a Matrix user ID"); mod tests { use std::convert::TryFrom; + #[cfg(feature = "serde")] use serde_json::{from_str, to_string}; use super::UserId; @@ -134,6 +138,7 @@ mod tests { assert!(user_id.is_historical()); } + #[cfg(feature = "rand")] #[test] fn generate_random_valid_user_id() { let user_id = UserId::new("example.com").expect("Failed to generate UserId."); @@ -146,11 +151,13 @@ mod tests { assert_eq!(id_str.len(), 25); } + #[cfg(feature = "rand")] #[test] fn generate_random_invalid_user_id() { assert!(UserId::new("").is_err()); } + #[cfg(feature = "serde")] #[test] fn serialize_valid_user_id() { assert_eq!( @@ -160,6 +167,7 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn deserialize_valid_user_id() { assert_eq!(