Improve your Rust APIs with the type state pattern

preview_player
Показать описание
Today I'm teaching you how to build Rust APIs that are impossible to misuse by taking advantage of generics and zero-sized types!

Chapters:
0:00 Intro
0:28 Example overview
2:30 First solution
4:20 Second solution
8:13 Third solution
14:18 Outro
Рекомендации по теме
Комментарии
Автор

📝Get your *FREE Rust cheat sheet* :

Corrections:
10:00 - PhantomData isn't needed here. The Locked and Unlocked structs are already zero-sized types.
11:40 - The lock method should return PasswordManager<Locked>

letsgetrusty
Автор

I instantly fell in love with this pattern as soon as I figured out what it's all about. It's the perfect use for Rust's amazing type system.

RoyaltyInTraining.
Автор

I like the idea of using "types" as "markers" of sorts (regarding using generics on a struct just for differentiation). Better than using a field as that's runtime data.This was a great little video. Helped me see things a little different. A "rust patterns" mini-series would be good. Definitely some distinctions from other languages.

jeffg
Автор

You mistyped the lock method it still returns an unlocked password manager

VictorGamerLOL
Автор

Brilliant thank you! PyO3 (the rust crate for python extensions) uses this method to confirm the user has the GIL (Global interpreter Lock). At the time I gave up trying to understand the phantom data, but thanks to you I understand now! Now if only there was a way to make the macros that crate uses less mysterious...

EngineerNick
Автор

Soon it might also be possible to define states in an enum using const generics. Currently this requires the unstable "adt_const_params" feature, otherwise you could only be allowed to use integer and char types which isn't really readable.
This would have the benefit that it's easier to see what states are possible currently there is no real connection between the Locked and Unlocked types and the PasswordManager other than the impl blocks.

Ether_Void
Автор

Wow man. First 12 hours with Rust and it has already blown my mind so many times.

codebycarlos
Автор

Amazing video. Thank you! This solution is very elegant. Thank you for exploring the initial, non-optimal solutions first. It makes it easy to see the benefits of the final solution.

diarmaidmac
Автор

This is the first time I understand PhantomData. Thanks!

jonesmartins
Автор

I'm pretty sure you don't have to specify the type of PhantomData since it would be done by the compiler, aside from that very small thing, this is one of your best videos so far. It's providing information on an intermidiate level while being explained very well!

vanish
Автор

Recently I have came across a situation where I had to do something similar and this video immediately came to my mind. Nice work!

varantavers
Автор

It’s a beautiful use of the type system. Definitely gives me something to think about.

TehKarmalizer
Автор

Nice, saw this once before in a "chaining builder" pattern that prevented setting the same property twice.

I personally would make UnlockedManager a newtype for &mut PasswordManager, that way, do don't need ownership and you get the re-lock for free when it drops.

kajacx
Автор

As an alternative implementation, we could have the unlock method return an owned token that is a required parameter for the list_passwords method. Upon locking, the token is consumed again by the PasswordManager.

embeddedbastler
Автор

Very interesting and illuminating ! A while back ago, I was heavily into generating code from UML state diagrams. Generated state machine code either would use a traditional state transition table or state classes. Now duplicated code isn't that much of a problem, if the code is generated anyway, however to avoid duplicatation I could also a use traditional inheritance. So "LockedPasswordManagerr" and "UnlockedPasswordManager" would both inherit from "PasswordManager" which would implement common code (here: "version()" and "encryption"). It never occurred to me, that I could do the same with generics.

flippert
Автор

This video is hot sauce. I had seen Phantom data before, but did not fully comprehend it. Nice work Bogdan.

TheZdannar
Автор

how would using just state: State waste memory? Isn't it also 0-sized?

CYXXYC
Автор

This is awesome! Almost the same thing was implemented in ATS2 Postiats socket library, which is basically a header files for interop between "C". It uses something like the phantom types but with the refinement types. So not only you can describe the exact flow for you api, but also bind this flow with actual values you pass into functions. This is done via dependent type system

trashhater
Автор

didnt know about zero types. really nice video. as always keep the great work up

andredasilva
Автор

Great! Great! Great! The best explanation of the Type State Pattern on YouTube! You rock man! How can we support your work?

leonardogomes