Make rand and serde dependencies optional

This commit is contained in:
Jonas Platte 2020-04-17 12:52:53 +02:00
parent 025e298274
commit 76a5a487d2
No known key found for this signature in database
GPG Key ID: 7D261D771D915378
12 changed files with 74 additions and 15 deletions

View File

@ -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)"

View File

@ -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

View File

@ -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"

View File

@ -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;

View File

@ -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<Self, Error> {
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!(

View File

@ -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<NonZeroU8, Error> {
/// 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<T, D::Error>
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))
})
}

View File

@ -63,6 +63,7 @@ macro_rules! common_impls {
}
}
#[cfg(feature = "serde")]
impl ::serde::Serialize for $id {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -72,6 +73,7 @@ macro_rules! common_impls {
}
}
#[cfg(feature = "serde")]
impl<'de> ::serde::Deserialize<'de> for $id {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where

View File

@ -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!(

View File

@ -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<Self, Error> {
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!(

View File

@ -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!(

View File

@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -164,12 +166,13 @@ impl Serialize for RoomVersionId {
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for RoomVersionId {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
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<RoomVersionId> 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::<RoomVersionId>(r#""io.ruma.1""#)

View File

@ -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<Self, Error> {
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!(