Skip to content

Commit fd748be

Browse files
authored
add a cast function (#85)
We'd like to have this in place for a tentative idea: convert from `InternalZpoolUuid` and `ExternalZpoolUuid` to a more general `ZpoolUuid`.
1 parent e750a12 commit fd748be

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed

crates/newtype-uuid/src/lib.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,82 @@ impl<T: TypedUuidKind> TypedUuid<T> {
298298
pub fn get_version(&self) -> Option<Version> {
299299
self.uuid.get_version()
300300
}
301+
302+
/// Converts the UUID to one with a different kind.
303+
///
304+
/// By default, UUID kinds are considered independent, and conversions
305+
/// between them must happen via the [`GenericUuid`] interface. But in some
306+
/// cases, there may be a relationship between two different UUID kinds, and
307+
/// you may wish to easily convert UUIDs from one kind to another.
308+
///
309+
/// Typically, a conversion from `TypedUuid<T>` to `TypedUuid<U>` is most
310+
/// useful when `T`'s semantics are a superset of `U`'s, or in other words,
311+
/// when every `TypedUuid<T>` is logically also a `TypedUuid<U>`.
312+
///
313+
/// For instance:
314+
///
315+
/// * Imagine you have [`TypedUuidKind`]s for different types of
316+
/// database connections, where `DbConnKind` is the general type
317+
/// and `PgConnKind` is a specific kind for Postgres.
318+
/// * Since every Postgres connection is also a database connection,
319+
/// a cast from `TypedUuid<PgConnKind>` to `TypedUuid<DbConnKind>`
320+
/// makes sense.
321+
/// * The inverse cast would not make sense, as a database connection may not
322+
/// necessarily be a Postgres connection.
323+
///
324+
/// This interface provides an alternative, safer way to perform this
325+
/// conversion. Indicate your intention to allow a conversion between kinds
326+
/// by implementing `From<T> for U`, as shown in the example below.
327+
///
328+
/// # Examples
329+
///
330+
/// ```
331+
/// use newtype_uuid::{TypedUuid, TypedUuidKind, TypedUuidTag};
332+
///
333+
/// // Let's say that these UUIDs represent repositories for different
334+
/// // version control systems, such that you have a generic RepoKind:
335+
/// pub enum RepoKind {}
336+
/// impl TypedUuidKind for RepoKind {
337+
/// fn tag() -> TypedUuidTag {
338+
/// const TAG: TypedUuidTag = TypedUuidTag::new("repo");
339+
/// TAG
340+
/// }
341+
/// }
342+
///
343+
/// // You also have more specific kinds:
344+
/// pub enum GitRepoKind {}
345+
/// impl TypedUuidKind for GitRepoKind {
346+
/// fn tag() -> TypedUuidTag {
347+
/// const TAG: TypedUuidTag = TypedUuidTag::new("git_repo");
348+
/// TAG
349+
/// }
350+
/// }
351+
/// // (and HgRepoKind, JujutsuRepoKind, etc...)
352+
///
353+
/// // First, define a `From` impl. This impl indicates your desire
354+
/// // to convert from one kind to another.
355+
/// impl From<GitRepoKind> for RepoKind {
356+
/// fn from(value: GitRepoKind) -> Self {
357+
/// match value {}
358+
/// }
359+
/// }
360+
///
361+
/// // Now you can convert between them:
362+
/// let git_uuid: TypedUuid<GitRepoKind> =
363+
/// TypedUuid::from_u128(0xe9245204_34ea_4ca7_a1c6_2e94fa49df61);
364+
/// let repo_uuid: TypedUuid<RepoKind> = git_uuid.cast();
365+
/// ```
366+
#[inline]
367+
#[must_use]
368+
pub const fn cast<U: TypedUuidKind>(self) -> TypedUuid<U>
369+
where
370+
T: Into<U>,
371+
{
372+
TypedUuid {
373+
uuid: self.uuid,
374+
_phantom: PhantomData,
375+
}
376+
}
301377
}
302378

303379
// ---

0 commit comments

Comments
 (0)