Add random generation constructors.

This commit is contained in:
Jimmy Cuadra 2016-07-26 06:00:30 -07:00
parent 91711c6544
commit 20cfd5200e
3 changed files with 108 additions and 2 deletions

9
Cargo.lock generated
View File

@ -3,6 +3,7 @@ name = "ruma-identifiers"
version = "0.1.0"
dependencies = [
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.0-rc3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.8.0-rc1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -74,6 +75,14 @@ name = "num-traits"
version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rand"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "0.1.73"

View File

@ -12,6 +12,7 @@ version = "0.1.0"
[dependencies]
lazy_static = "0.2.1"
rand = "0.3.14"
regex = "0.1.73"
serde = "0.8.0-rc3"
url = "1.1.1"

View File

@ -6,6 +6,7 @@
#[macro_use]
extern crate lazy_static;
extern crate rand;
extern crate regex;
extern crate serde;
extern crate url;
@ -16,6 +17,7 @@ extern crate serde_json;
use std::convert::TryFrom;
use std::fmt::{Display, Formatter, Result as FmtResult};
use rand::{Rng, thread_rng};
use regex::Regex;
use serde::{Deserialize, Deserializer, Error as SerdeError, Serialize, Serializer};
use serde::de::Visitor;
@ -80,8 +82,8 @@ pub struct EventId {
/// A Matrix room alias ID.
///
/// A `RoomAliasId` is generated randomly or converted from a string slice, and can be converted
/// back into a string as needed.
/// A `RoomAliasId` is converted from a string slice, and can be converted back into a string as
/// needed.
///
/// ```
/// # #![feature(try_from)]
@ -155,6 +157,10 @@ fn display(f: &mut Formatter, sigil: char, localpart: &str, hostname: &Host, por
}
}
fn generate_localpart(length: usize) -> String {
thread_rng().gen_ascii_chars().take(length).collect()
}
fn parse_id<'a>(required_sigil: char, id: &'a str) -> Result<(&'a str, Host, u16), Error> {
if id.len() > MAX_BYTES {
return Err(Error::MaximumLengthExceeded);
@ -193,6 +199,21 @@ fn parse_id<'a>(required_sigil: char, id: &'a str) -> Result<(&'a str, Host, u16
}
impl EventId {
/// Attempts to generate an `EventId` for the given origin server with a localpart consisting
/// of 18 random ASCII characters.
///
/// Fails if the given origin server name cannot be parsed as a valid host.
pub fn new(server_name: &str) -> Result<Self, Error> {
let event_id = format!("${}:{}", generate_localpart(18), server_name);
let (opaque_id, host, port) = parse_id('$', &event_id)?;
Ok(EventId {
hostname: host,
opaque_id: opaque_id.to_string(),
port: port,
})
}
/// Returns a `Host` for the event ID, containing the server name (minus the port) of the
/// originating homeserver.
///
@ -213,6 +234,21 @@ impl EventId {
}
impl RoomId {
/// Attempts to generate a `RoomId` for the given origin server with a localpart consisting of
/// 18 random ASCII characters.
///
/// Fails if the given origin server name cannot be parsed as a valid host.
pub fn new(server_name: &str) -> Result<Self, Error> {
let room_id = format!("!{}:{}", generate_localpart(18), server_name);
let (opaque_id, host, port) = parse_id('!', &room_id)?;
Ok(RoomId {
hostname: host,
opaque_id: opaque_id.to_string(),
port: port,
})
}
/// Returns a `Host` for the room ID, containing the server name (minus the port) of the
/// originating homeserver.
///
@ -253,6 +289,21 @@ impl RoomAliasId {
}
impl UserId {
/// Attempts to generate a `UserId` for the given origin server with a localpart consisting of
/// 12 random ASCII characters.
///
/// Fails if the given origin server name cannot be parsed as a valid host.
pub fn new(server_name: &str) -> Result<Self, Error> {
let user_id = format!("@{}:{}", generate_localpart(12), server_name);
let (localpart, host, port) = parse_id('@', &user_id)?;
Ok(UserId {
hostname: host,
localpart: localpart.to_string(),
port: port,
})
}
/// Returns a `Host` for the user ID, containing the server name (minus the port) of the
/// originating homeserver.
///
@ -488,6 +539,21 @@ mod tests {
);
}
#[test]
fn generate_random_valid_event_id() {
let event_id = EventId::new("example.com")
.expect("Failed to generate EventId.")
.to_string();
assert!(event_id.to_string().starts_with('$'));
assert_eq!(event_id.len(), 31);
}
#[test]
fn generate_random_invalid_event_id() {
assert!(EventId::new("").is_err());
}
#[test]
fn serialize_valid_event_id() {
assert_eq!(
@ -651,6 +717,21 @@ mod tests {
);
}
#[test]
fn generate_random_valid_room_id() {
let room_id = RoomId::new("example.com")
.expect("Failed to generate RoomId.")
.to_string();
assert!(room_id.to_string().starts_with('!'));
assert_eq!(room_id.len(), 31);
}
#[test]
fn generate_random_invalid_room_id() {
assert!(RoomId::new("").is_err());
}
#[test]
fn serialize_valid_room_id() {
assert_eq!(
@ -733,6 +814,21 @@ mod tests {
);
}
#[test]
fn generate_random_valid_user_id() {
let user_id = UserId::new("example.com")
.expect("Failed to generate UserId.")
.to_string();
assert!(user_id.to_string().starts_with('@'));
assert_eq!(user_id.len(), 25);
}
#[test]
fn generate_random_invalid_user_id() {
assert!(UserId::new("").is_err());
}
#[test]
fn serialize_valid_user_id() {
assert_eq!(