Spacc BBS Spacc BBS
    • Categorie
    • Recenti
    • Tag
    • Popolare
    • Mondo
    • Utenti
    • Gruppi
    • Registrati
    • Accedi
    La nuova BBS è in fase Alpha. I post precedenti al 22 luglio 2024 potrebbero non essere trasferibili, ma rimarranno disponibili per la lettura su /old/.

    Rusteceans of the Fediverse, can you help me with a declarative macro problem?

    Pianificato Fissato Bloccato Spostato Uncategorized
    rustlang
    23 Post 2 Autori 50 Visualizzazioni
    Caricamento altri post
    • Da Vecchi a Nuovi
    • Da Nuovi a Vecchi
    • Più Voti
    Rispondi
    • Topic risposta
    Effettua l'accesso per rispondere
    Questa discussione è stata eliminata. Solo gli utenti con diritti di gestione possono vederla.
    • slatian@pleroma.envs.netS Questo utente è esterno a questo forum
      slatian@pleroma.envs.net
      ultima modifica di

      Rusteceans of the Fediverse, can you help me with a declarative macro problem?

      Assum I want to something similar to this:

      sql_schema!{
          SchemaName
          enum FooTable = "foo" {
               FooBarField = "foo_bar",
               FooBazField = "foo_baz",
          }
          enum OtherTable = "other {
               // …
          }
      }
      

      into:

      • An enum SchemaName that has the members FooTable and OtherTable.
      • Two enums FooTable and OtherTable with an automatically implemented trait that returns the given strings.
      • Another enum SchemaNameField that has the members FooTable(FooTable) and OtherTable(OtherTable)

      Is that at all possible with declarative macros? How do I structure this without it turning into a recursion nightmare?

      #rustlang

      steffo@a.junimo.partyS slatian@pleroma.envs.netS 3 Risposte Ultima Risposta Rispondi Cita 0
      • steffo@a.junimo.partyS Questo utente è esterno a questo forum
        steffo@a.junimo.party @slatian@pleroma.envs.net
        ultima modifica di

        @slatian i think it should be? let me try real quick

        1 Risposta Ultima Risposta Rispondi Cita 0
        • steffo@a.junimo.partyS Questo utente è esterno a questo forum
          steffo@a.junimo.party @slatian@pleroma.envs.net
          ultima modifica di steffo@a.junimo.party

          @slatian what are the field strings for?

          slatian@pleroma.envs.netS 1 Risposta Ultima Risposta Rispondi Cita 0
          • slatian@pleroma.envs.netS Questo utente è esterno a questo forum
            slatian@pleroma.envs.net @steffo@a.junimo.party
            ultima modifica di

            @steffo@a.junimo.party That's supposed to become a mapping for fields in an sql database to rust enums and the strings are the actual table and column names in the database.

            And now that you'Re asking I actually have an example implementation (generated by a lua script):

            • https://codeberg.org/unobtanium/unobtanium/src/branch/main/lib-unobtanium/src/database/tables.rs
            • https://codeberg.org/unobtanium/unobtanium/src/branch/main/lib-unobtanium/src/database/fields.rs
            steffo@a.junimo.partyS 1 Risposta Ultima Risposta Rispondi Cita 0
            • steffo@a.junimo.partyS Questo utente è esterno a questo forum
              steffo@a.junimo.party @slatian@pleroma.envs.net
              ultima modifica di

              @slatian how can i get the identifiers for the enum variants of the fields?

              like

              Key,
              MimeParameterId,
              MimetypeId,
              Value,
              slatian@pleroma.envs.netS 1 Risposta Ultima Risposta Rispondi Cita 0
              • slatian@pleroma.envs.netS Questo utente è esterno a questo forum
                slatian@pleroma.envs.net @steffo@a.junimo.party
                ultima modifica di

                @steffo@a.junimo.party That's the inner enums, so FooBarField and FooBazField in my example above.

                steffo@a.junimo.partyS 2 Risposte Ultima Risposta Rispondi Cita 0
                • steffo@a.junimo.partyS Questo utente è esterno a questo forum
                  steffo@a.junimo.party @slatian@pleroma.envs.net
                  ultima modifica di

                  Questo post è eliminato!
                  1 Risposta Ultima Risposta Rispondi Cita 0
                  • steffo@a.junimo.partyS Questo utente è esterno a questo forum
                    steffo@a.junimo.party @slatian@pleroma.envs.net
                    ultima modifica di

                    @slatian where is SchemaName used then? is it BaseTable?

                    slatian@pleroma.envs.netS 1 Risposta Ultima Risposta Rispondi Cita 0
                    • slatian@pleroma.envs.netS Questo utente è esterno a questo forum
                      slatian@pleroma.envs.net @steffo@a.junimo.party
                      ultima modifica di

                      @steffo@a.junimo.party

                      I've noticed, that I forgot to link a file, this one is where everything gets tied together:

                      https://codeberg.org/unobtanium/unobtanium/src/branch/main/lib-unobtanium/src/database/schemas.rs

                      steffo@a.junimo.partyS slatian@pleroma.envs.netS 2 Risposte Ultima Risposta Rispondi Cita 0
                      • steffo@a.junimo.partyS Questo utente è esterno a questo forum
                        steffo@a.junimo.party @slatian@pleroma.envs.net
                        ultima modifica di

                        @slatian yeah, that can be done, the only impossible thing is appending Field to identifier names, as that would require a procedural macro (an external one would also work)

                        shouldn't be an issue because in one case they're enums names and in the other they're enum variants, and the two can be disambiguated

                        slatian@pleroma.envs.netS 1 Risposta Ultima Risposta Rispondi Cita 0
                        • slatian@pleroma.envs.netS Questo utente è esterno a questo forum
                          slatian@pleroma.envs.net @steffo@a.junimo.party
                          ultima modifica di

                          @steffo@a.junimo.party In that case I think it would be easier to write the whole thing as a procedural macro?

                          steffo@a.junimo.partyS 1 Risposta Ultima Risposta Rispondi Cita 0
                          • steffo@a.junimo.partyS Questo utente è esterno a questo forum
                            steffo@a.junimo.party @slatian@pleroma.envs.net
                            ultima modifica di

                            @slatian unsure, give me a few mins and i'm (re)writing the macro_rules like that

                            1 Risposta Ultima Risposta Rispondi Cita 0
                            • slatian@pleroma.envs.netS Questo utente è esterno a questo forum
                              slatian@pleroma.envs.net @slatian@pleroma.envs.net
                              ultima modifica di

                              @steffo@a.junimo.party Sorry, I haven't touched that code in quite a while … And I also didn't expect anyone to dive in this deep :drgn_heart:

                              The Declaration for my example would be:

                              sql_schema!{
                                  BaseTable
                                  enum MimeParameter = "mime_parameter" {
                                       Key = "key",
                                       MimeParameterId = "mime_parameter_id",
                                       // …
                                  }
                                  enum Mimetype = "mimetype" {
                                       // …
                                  }
                                  enum Origin = "origin" {
                                      // …
                                  }
                                  // …
                              }
                              
                              steffo@a.junimo.partyS 1 Risposta Ultima Risposta Rispondi Cita 0
                              • steffo@a.junimo.partyS Questo utente è esterno a questo forum
                                steffo@a.junimo.party @slatian@pleroma.envs.net
                                ultima modifica di steffo@a.junimo.party

                                @slatian something like this?

                                pub trait Table {
                                fn sql_safe_table_name(&self) -> &'static str;
                                }

                                pub trait Field {
                                fn sql_safe_field_name(&self) -> &'static str;
                                }

                                macro_rules! sql_schema {
                                {
                                $schema_name:ident,
                                $(
                                enum $table_name:ident = $table_value:literal {
                                $( $field_name:ident = $field_value:literal ),*
                                }
                                )*
                                } => {
                                pub enum $schema_name {
                                $( $table_name ),*
                                }

                                impl Table for $schema_name {
                                fn sql_safe_table_name(&self) -> &'static str {
                                match self {
                                $( $schema_name::$table_name => $table_value ),*
                                }
                                }
                                }

                                $(
                                // it's not possible to concatenate things to identifiers without the use of a proc macro
                                // so we just re-use $table_name
                                pub enum $table_name {
                                $( $field_name ),*
                                }

                                impl Field for $table_name {
                                fn sql_safe_field_name(&self) -> &'static str {
                                match self {
                                $( $table_name::$field_name => $field_value ),*
                                }
                                }
                                }
                                )*
                                }
                                }

                                sql_schema! {
                                BaseTable,
                                enum MimeParameter = "mime_parameter" {
                                Key = "key",
                                MimeParameterId = "mime_parameter_id"
                                }
                                enum Mimetype = "mimetype" {
                                Charset = "charset"
                                // …
                                }
                                }

                                you can use cargo expand to see what it generates

                                slatian@pleroma.envs.netS 1 Risposta Ultima Risposta Rispondi Cita 0
                                • slatian@pleroma.envs.netS Questo utente è esterno a questo forum
                                  slatian@pleroma.envs.net @steffo@a.junimo.party
                                  ultima modifica di

                                  @steffo@a.junimo.party It took a while for me to wrap my Brain around this :drgn_sparkle: <- didn't expect it to be that … simple and especially readable.

                                  Given that I can almost 1:1 copy this into criterium (licensed LGPL-3.0-only): May I? If yes, what name do you want in the copyright header?

                                  steffo@a.junimo.partyS 1 Risposta Ultima Risposta Rispondi Cita 0
                                  • steffo@a.junimo.partyS Questo utente è esterno a questo forum
                                    steffo@a.junimo.party @slatian@pleroma.envs.net
                                    ultima modifica di

                                    @slatian sure! you can add Stefano Pigozzi <me@steffo.eu> to the contributors section of Cargo.toml if you want, but dw, it's just a snippet of code that fit in a fedi post

                                    steffo@a.junimo.partyS 1 Risposta Ultima Risposta Rispondi Cita 0
                                    • steffo@a.junimo.partyS Questo utente è esterno a questo forum
                                      steffo@a.junimo.party @steffo@a.junimo.party
                                      ultima modifica di steffo@a.junimo.party

                                      @slatian a thing to be aware of, $(),* does not allow trailing commas, so this would work

                                          enum Mimetype = "mimetype" {
                                      Charset = "charset"
                                      }

                                      but this would give a weird error

                                          enum Mimetype = "mimetype" {
                                      Charset = "charset",
                                      }
                                      slatian@pleroma.envs.netS 1 Risposta Ultima Risposta Rispondi Cita 0
                                      • slatian@pleroma.envs.netS Questo utente è esterno a questo forum
                                        slatian@pleroma.envs.net @steffo@a.junimo.party
                                        ultima modifica di

                                        @steffo@a.junimo.party

                                        The optional comma could just be eaten by a $(…),* $(,)?

                                        Or am I missing something? (I don't write a lot of macros.)

                                        steffo@a.junimo.partyS 4 Risposte Ultima Risposta Rispondi Cita 0
                                        • steffo@a.junimo.partyS Questo utente è esterno a questo forum
                                          steffo@a.junimo.party @slatian@pleroma.envs.net
                                          ultima modifica di

                                          @slatian yep

                                          1 Risposta Ultima Risposta Rispondi Cita 0
                                          • steffo@a.junimo.partyS Questo utente è esterno a questo forum
                                            steffo@a.junimo.party @slatian@pleroma.envs.net
                                            ultima modifica di

                                            Questo post è eliminato!
                                            1 Risposta Ultima Risposta Rispondi Cita 0
                                            • Primo post
                                              Ultimo post