Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First release: make default async, replace specs-generator system, trim down and organize files, etc. #27

Merged
merged 270 commits into from
Mar 1, 2022

Conversation

lcsmuller
Copy link
Collaborator

@lcsmuller lcsmuller commented Feb 18, 2022

What?

This PR outlines implementation details for the first release of Concord, it differs from Orca in a couple aspects:

More

Changes for the user wishing to migrate their codebase to Concord

Why?

  • Make async default #19
    • Performing requests synchronously blocks the event loop, consequently making them unresponsive. Because the WebSockets was already implemented in a single-thread, asynchronous fashion, it makes sense for the requests to take advantage of it too.
  • Refactor specs generator, JSON marshalling methods, lists #21
    • specs-gen was not flexible and required modification of its source-code for any little fix or change. It relied on a custom-made JSON specs system that would be fed to it for generating code. gencodecs takes advantage of well-known C Preprocessor tools - in case a custom-type or behavior is required the user can create a custom macro wrapping for it, without a need to modify gencodecs source code directly.
    • json_extract() is not debugging friendly because it relies on variadic arguments for fetching JSON values, without any kind of type-checking to guarantee correctness of argument and expected JSON type.
    • json_inject() is not debugging friendly for the same reasons outlined above for json_extract(), and the its size was not respected, leading to crashes if the buffer it not large enough to accommodate the JSON.

How?

  • Make async default #19
    See Async requests are now the default behavior
  • Refactor specs generator, JSON marshalling methods, lists #21
    • specs-code JSON specs for code conversion, the following would be fed to specs/main.c, which would then generated code and comments via the specs-gen.c implementation.
     {
       "namespace": ["discord"],
       "comment":"https://discord.com/developers/docs/resources/channel",
       "defs":
       [
         {
           "title":"Message Reference Structure",
           "comment":"https://discord.com/developers/docs/resources/channel#message-object-message-reference-structure",
           "namespace":["message"],
           "struct":"reference",
           "fields": [
             {"name":"message_id", "type":{"base":"char", "dec":"*", "converter":"snowflake"}, "option":true, "inject_if_not":0},
             {"name":"channel_id", "type":{"base":"char", "dec":"*", "converter":"snowflake"}, "option":true, "inject_if_not":0},
             {"name":"guild_id", "type":{"base":"char", "dec":"*", "converter":"snowflake"}, "option":true, "inject_if_not":0},
             {"name":"fail_if_not_exists", "type":{"base":"bool"}, "option":true, "inject_if_not":false}
           ]
         }
       ]
     }
    the same conversion as above can be accomplished with gencodecs macros as follows, those macros can be expanded separately to ensure easier debuggability (see gencodecs/Makefile) or applied directly to code
     /** @brief https://discord.com/developers/docs/resources/channel#message-object-message-reference-structure */
     STRUCT(discord_message_reference)
          FIELD_SNOWFLAKE(message_id)
          FIELD_SNOWFLAKE(channel_id)
          FIELD_SNOWFLAKE(guild_id)
          FIELD(fail_if_not_exists, bool, true)
     STRUCT_END
    • json_extract() unsafe conversion
     char json[] = "\"foo\":\"this is a string\"";
     int a;
     
     json_extract(json, sizeof(json), "(foo):s", &a); // foo will match 'a' to a string, despite the fact that it should be a int
    jsmn-find fixes this by simply fetching the JSON token as a string, and leaving the conversion to the user.
     char json[] = "\"foo\":\"this is a string\"";
     int a;
     
     jsmnf *root = jsmnf_init();
     jsmnf_start(root, json, sizeof(json));
     
     jsmnf *f = jsmnf_find(f, "foo", strlen("foo"));
     if (f && f->val->type == JSMN_PRIMITIVE) {
       a = (int)strtol(json + f->val->start, NULL, 10); // conversion is type-checked and done on user-side
     }
    • json_inject() unsafe conversion
     char buf[1024];
     int a = 10;
     
     json_inject(buf, sizeof(buf), "(foo):s", a); // foo will attempt to read 'a' as a string, despite the fact that it should be a int
    json-build fixes this by strict type-checking via its function parameters
     char buf[1024];
     int a = 10;
     jsonb b;
     
     jsonb_init(&b);
     jsonb_object(&b, buf, sizeof(buf));
     {
       jsonb_key(&b, buf, sizeof(buf), "foo", strlen("foo"));
       jsonb_number(&b, buf, sizeof(buf), a); // type-checking done here
       jsonb_object_pop(&b, buf, sizeof(buf));
     }

lcsmuller and others added 30 commits January 14, 2022 19:24
…h; make discord_gateway REST function default to asynchronous; type-safe assignment; make it possible to toggle a request to be sync by passing it the object address
…el, discord_execute_webhook() wrong return type
lcsmuller added a commit to Cogmasters/concord-dev-docs that referenced this pull request Mar 1, 2022
@lcsmuller lcsmuller added the enhancement New feature or request label Mar 1, 2022
@lcsmuller lcsmuller linked an issue Mar 1, 2022 that may be closed by this pull request
@lcsmuller lcsmuller marked this pull request as ready for review March 1, 2022 18:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Missing things.
6 participants