A better Rust ATProto crate
1//! Common builder types shared across all builders
2//!
3//! Generates the Set, Unset, IsSet, IsUnset types that all builders use.
4//! These are generated once per crate and re-used by all builders.
5
6use proc_macro2::TokenStream;
7use quote::quote;
8
9/// Generate the common builder types module
10///
11/// This should be generated once at the root of the generated code
12/// (e.g., in lib.rs or a builder_types module).
13pub fn generate_common_types() -> TokenStream {
14 quote! {
15 /// Marker type indicating a builder field has been set
16 pub struct Set<T>(pub T);
17
18 impl<T> Set<T> {
19 /// Extract the inner value
20 #[inline]
21 pub fn into_inner(self) -> T {
22 self.0
23 }
24 }
25
26 /// Marker type indicating a builder field has not been set
27 pub struct Unset;
28
29 /// Trait indicating a builder field is set (has a value)
30 #[rustversion::attr(
31 since(1.78.0),
32 diagnostic::on_unimplemented(
33 message = "the field `{Self}` was not set, but this method requires it to be set",
34 label = "the field `{Self}` was not set"
35 )
36 )]
37 pub trait IsSet: private::Sealed {}
38
39 /// Trait indicating a builder field is unset (no value yet)
40 #[rustversion::attr(
41 since(1.78.0),
42 diagnostic::on_unimplemented(
43 message = "the field `{Self}` was already set, but this method requires it to be unset",
44 label = "the field `{Self}` was already set"
45 )
46 )]
47 pub trait IsUnset: private::Sealed {}
48
49 impl<T> IsSet for Set<T> {}
50 impl IsUnset for Unset {}
51
52 mod private {
53 /// Sealed trait to prevent external implementations
54 pub trait Sealed {}
55 impl<T> Sealed for super::Set<T> {}
56 impl Sealed for super::Unset {}
57 }
58 }
59}