<commit_before>* About
  CL-MTGNET is a client library for the MTGNet RPC protocol. The library
  handles all the details of marshalling and unmarshalling, including
  matching out-of-order responses to the appropriate request.

* Dependencies
  This library depends on the CL-NETSTRING+ library, as well as the
  quicklisp-installable CL-JSON and TRIVIAL-UTF-8 libs.

* API
  Remote methods are treated like FFI calls: the client creates
  definitions for the methods it wishes to use, and can then call
  those methods as if they were local functions.

** Method Definition
   Most clients will want to use the high-level macros to define
   method functions that handle the details of calling. The method
   definition macro is relatively simple:

  :(defmacro define-rpc-method ((method &optional service  &key notification) &body args))

   =method= and =service= are symbols naming the method and the
   service =method= belongs to. =define-rpc-method= will create a
   function named =<method>=, which takes a socket stream, a symbol
   naming the service, and the arguments of the method. If =service=
   is provided, the function will be named =<service>-<method>= and
   will not take a service symbol as a parameter. Note that both
   =method= and =service= symbols will be processed by CL-JSON, so
   the standard name-mangling applies (e.g. =describe-method= will
   become =describeMethod= when sent to the server).

   If =notification= is not supplied or is =nil=, the function will
   return a future object that will return the value of the method (or
   signal an error) when =wait= is called on it. If =notification= is
   not =nil=, the function will return immediately with no value
   (since no response is expected from the server).

*** Examples
  : ;; Define a method without specifying a service
  : (define-rpc-method
  :    ;; Method name
  :    (describe-method)
  :    ;; Method arguments
  :    method-name)
  :
  : ;; Invoke the method on the 'server' service
  : ;; (wait (describe-method sock 'server "version")) => [...]
  :
  : ;; Define a method on a specific service
  : (define-rpc-method (describe-method server) method-name)
  :
  : ;; (wait (server-describe-method "version")) => [...]
  :
  : ;; Define a notification method
  : (define-rpc-method (poke server :notification t) msg)
  :
  : ;; Note the lack of a WAIT call here
  : ;; (server-poke "Poked for no reason!") => No value

** Batched Calls
   The MTGNet protocol features the ability to send requests to the
   server in a batch, with the guarantee that the server will hold the
   responses for those calls until they're all ready before returning
   them. Clients can submit a batch of calls using the
   =with-batch-calls= macro:
  : ;; With STREAM, DESCRIBE-METHOD and VERSION defined elsewhere...
  : (let (describe-future
  :       version-future)
  :   (with-batch-calls
  :       (setf describe-future (server-describe-method sock "version")
  :             version-future (server-version sock)))
  :   (values (wait description-future)
  :           ;; This will return immediately
  :           (wait version-future)))<commit_msg>Fix formatting of code blocks in the README.<commit_after>* About
  CL-MTGNET is a client library for the MTGNet RPC protocol. The library
  handles all the details of marshalling and unmarshalling, including
  matching out-of-order responses to the appropriate request.

* Dependencies
  This library depends on the CL-NETSTRING+ library, as well as the
  quicklisp-installable CL-JSON and TRIVIAL-UTF-8 libs.

* API
  Remote methods are treated like FFI calls: the client creates
  definitions for the methods it wishes to use, and can then call
  those methods as if they were local functions.

** Method Definition
   Most clients will want to use the high-level macros to define
   method functions that handle the details of calling. The method
   definition macro is relatively simple:

#+begin_src lisp
  (defmacro define-rpc-method ((method &optional service  &key notification) &body args))
#+end_src

   =method= and =service= are symbols naming the method and the
   service =method= belongs to. =define-rpc-method= will create a
   function named =<method>=, which takes a socket stream, a symbol
   naming the service, and the arguments of the method. If =service=
   is provided, the function will be named =<service>-<method>= and
   will not take a service symbol as a parameter. Note that both
   =method= and =service= symbols will be processed by CL-JSON, so
   the standard name-mangling applies (e.g. =describe-method= will
   become =describeMethod= when sent to the server).

   If =notification= is not supplied or is =nil=, the function will
   return a future object that will return the value of the method (or
   signal an error) when =wait= is called on it. If =notification= is
   not =nil=, the function will return immediately with no value
   (since no response is expected from the server).

*** Examples
#+begin_src lisp
  ;; Define a method without specifying a service
  (define-rpc-method
     ;; Method name
     (describe-method)
     ;; Method arguments
     method-name)
  
  ;; Invoke the method on the 'server' service
  ;; (wait (describe-method sock 'server "version")) => [...]
  
  ;; Define a method on a specific service
  (define-rpc-method (describe-method server) method-name)
  
  ;; (wait (server-describe-method "version")) => [...]
  
  ;; Define a notification method
  (define-rpc-method (poke server :notification t) msg)
  
  ;; Note the lack of a WAIT call here
  ;; (server-poke "Poked for no reason!") => No value
#+end_src

** Batched Calls
   The MTGNet protocol features the ability to send requests to the
   server in a batch, with the guarantee that the server will hold the
   responses for those calls until they're all ready before returning
   them. Clients can submit a batch of calls using the
   =with-batch-calls= macro:
#+begin_src lisp
  ;; With STREAM, DESCRIBE-METHOD and VERSION defined elsewhere...
  (let (describe-future
        version-future)
    (with-batch-calls
        (setf describe-future (server-describe-method sock "version")
              version-future (server-version sock)))
    (values (wait description-future)
            ;; This will return immediately
            (wait version-future)))
#+end_src
{'fraction_non_alphanumeric': 0.08236220472440944, 'fraction_numerical': 0.00031496062992125983, 'mean_word_length': 3.4042995839112344, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3243902', 'n_tokens_mistral': 1773, 'n_tokens_neox': 1719, 'n_words': 805}