identifiers: Make RoomIdOrAliasId a DST
This commit is contained in:
parent
2d4dbfe42f
commit
313124a099
@ -356,7 +356,7 @@ pub struct ResultRoomEvents {
|
|||||||
|
|
||||||
/// Any groups that were requested.
|
/// Any groups that were requested.
|
||||||
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
||||||
pub groups: BTreeMap<GroupingKey, BTreeMap<RoomIdOrUserId, ResultGroup>>,
|
pub groups: BTreeMap<GroupingKey, BTreeMap<Box<RoomIdOrUserId>, ResultGroup>>,
|
||||||
|
|
||||||
/// Token that can be used to get the next batch of results, by passing as the `next_batch`
|
/// Token that can be used to get the next batch of results, by passing as the `next_batch`
|
||||||
/// parameter to the next call.
|
/// parameter to the next call.
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
use std::num::NonZeroU8;
|
use crate::{validate_delimited_id, Error};
|
||||||
|
|
||||||
use crate::{parse_id, Error};
|
pub fn validate(s: &str) -> Result<(), Error> {
|
||||||
|
validate_delimited_id(s, &['#', '!'])
|
||||||
pub fn validate(s: &str) -> Result<NonZeroU8, Error> {
|
|
||||||
parse_id(s, &['#', '!'])
|
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
convert::{TryFrom, TryInto},
|
convert::{TryFrom, TryInto},
|
||||||
fmt,
|
|
||||||
hint::unreachable_unchecked,
|
hint::unreachable_unchecked,
|
||||||
num::NonZeroU8,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{server_name::ServerName, RoomAliasId, RoomId};
|
use crate::{server_name::ServerName, RoomAliasId, RoomId};
|
||||||
@ -19,36 +17,32 @@ use crate::{server_name::ServerName, RoomAliasId, RoomId};
|
|||||||
/// # use std::convert::TryFrom;
|
/// # use std::convert::TryFrom;
|
||||||
/// # use ruma_identifiers::RoomIdOrAliasId;
|
/// # use ruma_identifiers::RoomIdOrAliasId;
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// RoomIdOrAliasId::try_from("#ruma:example.com").unwrap().as_ref(),
|
/// <&RoomIdOrAliasId>::try_from("#ruma:example.com").unwrap(),
|
||||||
/// "#ruma:example.com"
|
/// "#ruma:example.com"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// RoomIdOrAliasId::try_from("!n8f893n9:example.com").unwrap().as_ref(),
|
/// <&RoomIdOrAliasId>::try_from("!n8f893n9:example.com").unwrap(),
|
||||||
/// "!n8f893n9:example.com"
|
/// "!n8f893n9:example.com"
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Clone)]
|
#[repr(transparent)]
|
||||||
pub struct RoomIdOrAliasId {
|
pub struct RoomIdOrAliasId(str);
|
||||||
full_id: Box<str>,
|
|
||||||
colon_idx: NonZeroU8,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for RoomIdOrAliasId {
|
opaque_identifier_validated!(
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
RoomIdOrAliasId,
|
||||||
self.full_id.fmt(f)
|
ruma_identifiers_validation::room_id_or_alias_id::validate
|
||||||
}
|
);
|
||||||
}
|
|
||||||
|
|
||||||
impl RoomIdOrAliasId {
|
impl RoomIdOrAliasId {
|
||||||
/// Returns the local part (everything after the `!` or `#` and before the first colon).
|
/// Returns the local part (everything after the `!` or `#` and before the first colon).
|
||||||
pub fn localpart(&self) -> &str {
|
pub fn localpart(&self) -> &str {
|
||||||
&self.full_id[1..self.colon_idx.get() as usize]
|
&self.as_str()[1..self.colon_idx()]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the server name of the room (alias) ID.
|
/// Returns the server name of the room (alias) ID.
|
||||||
pub fn server_name(&self) -> &ServerName {
|
pub fn server_name(&self) -> &ServerName {
|
||||||
self.full_id[self.colon_idx.get() as usize + 1..].try_into().unwrap()
|
self.as_str()[self.colon_idx() + 1..].try_into().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this is a room id (starts with `'!'`)
|
/// Whether this is a room id (starts with `'!'`)
|
||||||
@ -63,15 +57,22 @@ impl RoomIdOrAliasId {
|
|||||||
|
|
||||||
/// Turn this `RoomIdOrAliasId` into `Either<RoomId, RoomAliasId>`
|
/// Turn this `RoomIdOrAliasId` into `Either<RoomId, RoomAliasId>`
|
||||||
#[cfg(feature = "either")]
|
#[cfg(feature = "either")]
|
||||||
pub fn into_either(self) -> either::Either<Box<RoomId>, Box<RoomAliasId>> {
|
pub fn into_either(self: Box<Self>) -> either::Either<Box<RoomId>, Box<RoomAliasId>> {
|
||||||
match self.variant() {
|
let variant = self.variant();
|
||||||
Variant::RoomId => either::Either::Left(self.as_str().try_into().unwrap()),
|
let boxed_str = self.into_owned();
|
||||||
Variant::RoomAliasId => either::Either::Right(self.as_str().try_into().unwrap()),
|
|
||||||
|
match variant {
|
||||||
|
Variant::RoomId => either::Either::Left(RoomId::from_owned(boxed_str)),
|
||||||
|
Variant::RoomAliasId => either::Either::Right(RoomAliasId::from_owned(boxed_str)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn colon_idx(&self) -> usize {
|
||||||
|
self.as_str().find(':').unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
fn variant(&self) -> Variant {
|
fn variant(&self) -> Variant {
|
||||||
match self.full_id.bytes().next() {
|
match self.as_str().bytes().next() {
|
||||||
Some(b'!') => Variant::RoomId,
|
Some(b'!') => Variant::RoomId,
|
||||||
Some(b'#') => Variant::RoomAliasId,
|
Some(b'#') => Variant::RoomAliasId,
|
||||||
_ => unsafe { unreachable_unchecked() },
|
_ => unsafe { unreachable_unchecked() },
|
||||||
@ -85,38 +86,22 @@ enum Variant {
|
|||||||
RoomAliasId,
|
RoomAliasId,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to create a new Matrix room ID or a room alias ID from a string representation.
|
impl From<Box<RoomId>> for Box<RoomIdOrAliasId> {
|
||||||
///
|
|
||||||
/// The string must either include the leading ! sigil, the localpart, a literal colon, and a
|
|
||||||
/// valid homeserver host or include the leading # sigil, the alias, a literal colon, and a
|
|
||||||
/// valid homeserver host.
|
|
||||||
fn try_from<S>(room_id_or_alias_id: S) -> Result<RoomIdOrAliasId, crate::Error>
|
|
||||||
where
|
|
||||||
S: AsRef<str> + Into<Box<str>>,
|
|
||||||
{
|
|
||||||
let colon_idx =
|
|
||||||
ruma_identifiers_validation::room_id_or_alias_id::validate(room_id_or_alias_id.as_ref())?;
|
|
||||||
Ok(RoomIdOrAliasId { full_id: room_id_or_alias_id.into(), colon_idx })
|
|
||||||
}
|
|
||||||
|
|
||||||
common_impls!(RoomIdOrAliasId, try_from, "a Matrix room ID or room alias ID");
|
|
||||||
|
|
||||||
impl From<Box<RoomId>> for RoomIdOrAliasId {
|
|
||||||
fn from(room_id: Box<RoomId>) -> Self {
|
fn from(room_id: Box<RoomId>) -> Self {
|
||||||
Self::try_from(room_id.as_str()).unwrap()
|
Self::try_from(room_id.as_str()).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Box<RoomAliasId>> for RoomIdOrAliasId {
|
impl From<Box<RoomAliasId>> for Box<RoomIdOrAliasId> {
|
||||||
fn from(room_alias_id: Box<RoomAliasId>) -> Self {
|
fn from(room_alias_id: Box<RoomAliasId>) -> Self {
|
||||||
Self::try_from(room_alias_id.as_str()).unwrap()
|
Self::try_from(room_alias_id.as_str()).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<RoomIdOrAliasId> for Box<RoomId> {
|
impl TryFrom<Box<RoomIdOrAliasId>> for Box<RoomId> {
|
||||||
type Error = Box<RoomAliasId>;
|
type Error = Box<RoomAliasId>;
|
||||||
|
|
||||||
fn try_from(id: RoomIdOrAliasId) -> Result<Box<RoomId>, Box<RoomAliasId>> {
|
fn try_from(id: Box<RoomIdOrAliasId>) -> Result<Box<RoomId>, Box<RoomAliasId>> {
|
||||||
match id.variant() {
|
match id.variant() {
|
||||||
Variant::RoomId => Ok(id.as_str().try_into().unwrap()),
|
Variant::RoomId => Ok(id.as_str().try_into().unwrap()),
|
||||||
Variant::RoomAliasId => Err(id.as_str().try_into().unwrap()),
|
Variant::RoomAliasId => Err(id.as_str().try_into().unwrap()),
|
||||||
@ -124,10 +109,10 @@ impl TryFrom<RoomIdOrAliasId> for Box<RoomId> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<RoomIdOrAliasId> for Box<RoomAliasId> {
|
impl TryFrom<Box<RoomIdOrAliasId>> for Box<RoomAliasId> {
|
||||||
type Error = Box<RoomId>;
|
type Error = Box<RoomId>;
|
||||||
|
|
||||||
fn try_from(id: RoomIdOrAliasId) -> Result<Box<RoomAliasId>, Box<RoomId>> {
|
fn try_from(id: Box<RoomIdOrAliasId>) -> Result<Box<RoomAliasId>, Box<RoomId>> {
|
||||||
match id.variant() {
|
match id.variant() {
|
||||||
Variant::RoomAliasId => Ok(id.as_str().try_into().unwrap()),
|
Variant::RoomAliasId => Ok(id.as_str().try_into().unwrap()),
|
||||||
Variant::RoomId => Err(id.as_str().try_into().unwrap()),
|
Variant::RoomId => Err(id.as_str().try_into().unwrap()),
|
||||||
@ -145,7 +130,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn valid_room_id_or_alias_id_with_a_room_alias_id() {
|
fn valid_room_id_or_alias_id_with_a_room_alias_id() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
RoomIdOrAliasId::try_from("#ruma:example.com")
|
<&RoomIdOrAliasId>::try_from("#ruma:example.com")
|
||||||
.expect("Failed to create RoomAliasId.")
|
.expect("Failed to create RoomAliasId.")
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
"#ruma:example.com"
|
"#ruma:example.com"
|
||||||
@ -155,7 +140,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn valid_room_id_or_alias_id_with_a_room_id() {
|
fn valid_room_id_or_alias_id_with_a_room_id() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
RoomIdOrAliasId::try_from("!29fhd83h92h0:example.com")
|
<&RoomIdOrAliasId>::try_from("!29fhd83h92h0:example.com")
|
||||||
.expect("Failed to create RoomId.")
|
.expect("Failed to create RoomId.")
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
"!29fhd83h92h0:example.com"
|
"!29fhd83h92h0:example.com"
|
||||||
@ -165,7 +150,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn missing_sigil_for_room_id_or_alias_id() {
|
fn missing_sigil_for_room_id_or_alias_id() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
RoomIdOrAliasId::try_from("ruma:example.com").unwrap_err(),
|
<&RoomIdOrAliasId>::try_from("ruma:example.com").unwrap_err(),
|
||||||
Error::MissingLeadingSigil
|
Error::MissingLeadingSigil
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -175,7 +160,7 @@ mod tests {
|
|||||||
fn serialize_valid_room_id_or_alias_id_with_a_room_alias_id() {
|
fn serialize_valid_room_id_or_alias_id_with_a_room_alias_id() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::to_string(
|
serde_json::to_string(
|
||||||
&RoomIdOrAliasId::try_from("#ruma:example.com")
|
<&RoomIdOrAliasId>::try_from("#ruma:example.com")
|
||||||
.expect("Failed to create RoomAliasId.")
|
.expect("Failed to create RoomAliasId.")
|
||||||
)
|
)
|
||||||
.expect("Failed to convert RoomAliasId to JSON."),
|
.expect("Failed to convert RoomAliasId to JSON."),
|
||||||
@ -188,7 +173,7 @@ mod tests {
|
|||||||
fn serialize_valid_room_id_or_alias_id_with_a_room_id() {
|
fn serialize_valid_room_id_or_alias_id_with_a_room_id() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::to_string(
|
serde_json::to_string(
|
||||||
&RoomIdOrAliasId::try_from("!29fhd83h92h0:example.com")
|
<&RoomIdOrAliasId>::try_from("!29fhd83h92h0:example.com")
|
||||||
.expect("Failed to create RoomId.")
|
.expect("Failed to create RoomId.")
|
||||||
)
|
)
|
||||||
.expect("Failed to convert RoomId to JSON."),
|
.expect("Failed to convert RoomId to JSON."),
|
||||||
@ -200,9 +185,10 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn deserialize_valid_room_id_or_alias_id_with_a_room_alias_id() {
|
fn deserialize_valid_room_id_or_alias_id_with_a_room_alias_id() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::from_str::<RoomIdOrAliasId>(r##""#ruma:example.com""##)
|
serde_json::from_str::<Box<RoomIdOrAliasId>>(r##""#ruma:example.com""##)
|
||||||
.expect("Failed to convert JSON to RoomAliasId"),
|
.expect("Failed to convert JSON to RoomAliasId"),
|
||||||
RoomIdOrAliasId::try_from("#ruma:example.com").expect("Failed to create RoomAliasId.")
|
<&RoomIdOrAliasId>::try_from("#ruma:example.com")
|
||||||
|
.expect("Failed to create RoomAliasId.")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,9 +196,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn deserialize_valid_room_id_or_alias_id_with_a_room_id() {
|
fn deserialize_valid_room_id_or_alias_id_with_a_room_id() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serde_json::from_str::<RoomIdOrAliasId>(r##""!29fhd83h92h0:example.com""##)
|
serde_json::from_str::<Box<RoomIdOrAliasId>>(r##""!29fhd83h92h0:example.com""##)
|
||||||
.expect("Failed to convert JSON to RoomId"),
|
.expect("Failed to convert JSON to RoomId"),
|
||||||
RoomIdOrAliasId::try_from("!29fhd83h92h0:example.com")
|
<&RoomIdOrAliasId>::try_from("!29fhd83h92h0:example.com")
|
||||||
.expect("Failed to create RoomAliasId.")
|
.expect("Failed to create RoomAliasId.")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -269,6 +269,7 @@ fn strip_lifetimes(field_type: &mut Type) -> bool {
|
|||||||
|| last_seg.ident == "RawJsonValue"
|
|| last_seg.ident == "RawJsonValue"
|
||||||
|| last_seg.ident == "RoomAliasId"
|
|| last_seg.ident == "RoomAliasId"
|
||||||
|| last_seg.ident == "RoomId"
|
|| last_seg.ident == "RoomId"
|
||||||
|
|| last_seg.ident == "RoomIdOrAliasId"
|
||||||
|| last_seg.ident == "RoomName"
|
|| last_seg.ident == "RoomName"
|
||||||
{
|
{
|
||||||
// The identifiers that need to be boxed `Box<T>` since they are DST's.
|
// The identifiers that need to be boxed `Box<T>` since they are DST's.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user