... This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
... If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.

(.require
 [library
  [lux (.except)
   ["$" documentation]
   [data
    [text (.only \n)
     ["%" \\injection]]
    [collection
     ["[0]" list]]]
   [meta
    [macro
     ["[0]" template]]]]]
 ["[0]" \\projection]
 [\\library
  ["[0]" /]])

(`` (the \\projection
      (List $.Documentation)
      (list ($.module \\projection._
                      "")

            ($.definition \\projection.unconsumed_input)
            ($.definition \\projection.empty_input)
            ($.definition \\projection.unexpected_value)
            ($.definition \\projection.value_mismatch)

            ($.definition (\\projection.Projection it)
              "A JSON projection.")

            ($.definition \\projection.value
              (%.message "Executes the projection against a JSON object."
                         \n "Verifies that all of the JSON was consumed by the projection.")
              ($.example (' (value projection json))))

            ($.definition \\projection.any
              "Just returns the JSON input without applying any logic.")

            (,, (template.with [<name>]
                  [(`` ($.definition <name>
                         (%.message "Reads a JSON value as " (,, (template.text [<name>])) ".")))]

                  [\\projection.null]
                  [\\projection.boolean]
                  [\\projection.number]
                  [\\projection.string]
                  ))

            (,, (template.with [<test> <check> <read>]
                  [(`` ($.definition <test>
                         (%.message "Asks whether a JSON value is a " (,, (template.text [<read>])) ".")))
                   (`` ($.definition <check>
                         (%.message "Ensures a JSON value is a " (,, (template.text [<read>])) ".")))]

                  [\\projection.boolean? \\projection.this_boolean ..boolean]
                  [\\projection.number?  \\projection.this_number  ..number]
                  [\\projection.string?  \\projection.this_string  ..string]
                  ))

            ($.definition \\projection.nullable
              "Enhances projection by adding NULL-handling."
              ($.example (' (nullable projection))))

            ($.definition \\projection.array
              "Parses the contents of a JSON array."
              ($.example (' (array projection))))

            ($.definition \\projection.object
              (%.message "Parses the contents of a JSON object."
                         \n "Use this with the 'field' combinator.")
              ($.example (' (object projection))))

            ($.definition \\projection.field
              (%.message "Parses a field inside a JSON object."
                         \n "Use this inside the 'object' combinator.")
              ($.example (' (field field_name projection))))

            ($.definition \\projection.dictionary
              "Parses a dictionary-like JSON object.")
            )))

(`` (the .public documentation
      (List $.Documentation)
      (list.partial ($.module /._
                              (%.message "Functionality for reading and writing values in the JSON format."
                                         \n "For more information, please see: http://www.json.org/"))

                    ($.definition /.Null)
                    ($.definition /.Boolean)
                    ($.definition /.Number)
                    ($.definition /.String)
                    ($.definition /.JSON)
                    ($.definition /.Array)
                    ($.definition /.Object)
                    ($.definition /.null?)
                    ($.definition /.object)
                    ($.definition /.equivalence)
                    ($.definition /.injection)
                    ($.definition /.format)

                    ($.definition /.json
                      "A simple way to produce JSON literals."
                      ($.comment "null")
                      ($.example (' (json #null)))

                      ($.comment "true")
                      ($.example (' (json #1)))

                      ($.comment "123.456")
                      ($.example (' (json +123.456)))

                      ($.comment "'this is a string'")
                      ($.example (' (json "this is a string")))

                      ($.comment "['this' 'is' 'an' 'array']")
                      ($.example (' (json ["this" "is" "an" "array"])))

                      ($.comment "{'this' 'is', 'an' 'object'}")
                      ($.example (' (json {"this" "is" "an" "object"}))))

                    ($.definition /.fields
                      "Get all the fields in a JSON object."
                      ($.example (' (fields json))))

                    ($.definition /.field
                      "A JSON object field getter."
                      ($.example (' (field key json))))

                    ($.definition /.has
                      "A JSON object field setter."
                      ($.example (' (has key value json))))

                    (,, (template.with [<name> <desc>]
                          [($.definition <name>
                             (%.message "A JSON object field getter for " <desc> "."))]

                          [/.boolean_field "booleans"]
                          [/.number_field  "numbers"]
                          [/.string_field  "strings"]
                          [/.array_field   "arrays"]
                          [/.object_field  "objects"]
                          ))

                    ..\\projection
                    )))
