parsers UPDATE notification children order irrelevant

Fixes #2080
diff --git a/src/parser_json.c b/src/parser_json.c
index f5851e9..71544fa 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -1594,7 +1594,30 @@
     lydjson_parse_name(lydctx->jsonctx->value, lydctx->jsonctx->value_len, &name, &name_len, &prefix, &prefix_len, &is_meta);
     lyjson_ctx_give_dynamic_value(lydctx->jsonctx, &value);
 
-    if (!is_meta || name_len || prefix_len) {
+    if ((lydctx->int_opts & LYD_INTOPT_EVENTTIME) && !parent && !is_meta && name_len && !prefix_len &&
+            !ly_strncmp("eventTime", name, name_len)) {
+        /* parse eventTime */
+        r = lyjson_ctx_next(lydctx->jsonctx, &status);
+        LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
+
+        if (status != LYJSON_STRING) {
+            LOGVAL(lydctx->jsonctx->ctx, LYVE_SYNTAX_JSON, "Expecting JSON %s but %s found.", lyjson_token2str(LYJSON_STRING),
+                    lyjson_token2str(status));
+            rc = LY_EVALID;
+            goto cleanup;
+        }
+
+        /* create node */
+        r = lyd_create_opaq(lydctx->jsonctx->ctx, name, name_len, prefix, prefix_len, prefix, prefix_len,
+                lydctx->jsonctx->value, lydctx->jsonctx->value_len, NULL, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, &node);
+        LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
+
+        /* validate the value */
+        r = lyd_parser_notif_eventtime_validate(node);
+        LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
+
+        goto node_parsed;
+    } else if (!is_meta || name_len || prefix_len) {
         /* get the schema node */
         r = lydjson_get_snode(lydctx, is_meta, prefix, prefix_len, name, name_len, parent, &snode, &ext);
         if (r == LY_ENOT) {
@@ -1748,6 +1771,7 @@
         }
     }
 
+node_parsed:
     /* finally connect the parsed node */
     lydjson_maintain_children(parent, first_p, &node, lydctx->parse_opts & LYD_PARSE_ORDERED ? 1 : 0, ext);
 
@@ -1906,19 +1930,18 @@
  * @param[in] jsonctx JSON parser context.
  * @param[in] name Name of the object.
  * @param[in] module Module name of the object, NULL if none expected.
- * @param[in] value Whether a value is expected.
  * @param[out] evnp Parsed envelope (opaque node).
  * @return LY_SUCCESS on success.
  * @return LY_ENOT if the specified object did not match.
  * @return LY_ERR value on error.
  */
 static LY_ERR
-lydjson_envelope(struct lyjson_ctx *jsonctx, const char *name, const char *module, ly_bool value, struct lyd_node **envp)
+lydjson_envelope(struct lyjson_ctx *jsonctx, const char *name, const char *module, struct lyd_node **envp)
 {
     LY_ERR rc = LY_SUCCESS, r;
     enum LYJSON_PARSER_STATUS status = lyjson_ctx_status(jsonctx);
-    const char *nam, *prefix, *val = NULL;
-    size_t nam_len, prefix_len, val_len = 0;
+    const char *nam, *prefix;
+    size_t nam_len, prefix_len;
     ly_bool is_meta;
 
     assert(status == LYJSON_OBJECT);
@@ -1953,24 +1976,9 @@
     r = lyjson_ctx_next(jsonctx, &status);
     LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
 
-    if (value) {
-        if (status != LYJSON_STRING) {
-            LOGVAL(jsonctx->ctx, LYVE_SYNTAX_JSON, "Expecting JSON %s but %s found.", lyjson_token2str(LYJSON_STRING),
-                    lyjson_token2str(status));
-            rc = LY_EVALID;
-            goto cleanup;
-        }
-
-        val = jsonctx->value;
-        val_len = jsonctx->value_len;
-
-        r = lyjson_ctx_next(jsonctx, &status);
-        LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
-    }
-
     /* create node */
-    rc = lyd_create_opaq(jsonctx->ctx, name, strlen(name), prefix, prefix_len, prefix, prefix_len, val, val_len,
-            NULL, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, envp);
+    rc = lyd_create_opaq(jsonctx->ctx, name, strlen(name), prefix, prefix_len, prefix, prefix_len, NULL, 0, NULL,
+            LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, envp);
     LY_CHECK_GOTO(rc, cleanup);
 
 cleanup:
@@ -1981,51 +1989,6 @@
     return rc;
 }
 
-/**
- * @brief Parse all expected non-data JSON objects of a RESTCONF notification message.
- *
- * @param[in] jsonctx JSON parser context.
- * @param[out] evnp Parsed envelope(s) (opaque node).
- * @param[out] int_opts Internal options for parsing the rest of YANG data.
- * @param[out] close_elem Number of parsed opened objects that need to be closed.
- * @return LY_SUCCESS on success.
- * @return LY_ERR value on error.
- */
-static LY_ERR
-lydjson_env_restconf_notif(struct lyjson_ctx *jsonctx, struct lyd_node **envp, uint32_t *int_opts, uint32_t *close_elem)
-{
-    LY_ERR rc = LY_SUCCESS, r;
-    struct lyd_node *child;
-
-    assert(envp && !*envp);
-
-    /* parse "notification" */
-    r = lydjson_envelope(jsonctx, "notification", "ietf-restconf", 0, envp);
-    LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
-
-    /* parse "eventTime" */
-    r = lydjson_envelope(jsonctx, "eventTime", NULL, 1, &child);
-    LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
-
-    /* insert */
-    lyd_insert_node(*envp, NULL, child, 0);
-
-    /* validate value */
-    r = lyd_parser_notif_eventtime_validate(child);
-    LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
-
-    /* RESTCONF notification */
-    *int_opts = LYD_INTOPT_NO_SIBLINGS | LYD_INTOPT_NOTIF;
-    *close_elem = 1;
-
-cleanup:
-    if (rc) {
-        lyd_free_tree(*envp);
-        *envp = NULL;
-    }
-    return rc;
-}
-
 LY_ERR
 lyd_parse_json_restconf(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
         struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
@@ -2033,7 +1996,7 @@
 {
     LY_ERR rc = LY_SUCCESS, r;
     struct lyd_json_ctx *lydctx = NULL;
-    enum LYJSON_PARSER_STATUS status;
+    struct lyd_node *node;
     uint32_t i, int_opts = 0, close_elem = 0;
 
     assert(ctx && in && lydctx_p);
@@ -2054,7 +2017,7 @@
         assert(parent);
 
         /* parse "input" */
-        rc = lydjson_envelope(lydctx->jsonctx, "input", lyd_node_module(parent)->name, 0, envp);
+        rc = lydjson_envelope(lydctx->jsonctx, "input", lyd_node_module(parent)->name, envp);
         LY_CHECK_GOTO(rc, cleanup);
 
         int_opts = LYD_INTOPT_WITH_SIBLINGS | LYD_INTOPT_RPC | LYD_INTOPT_ACTION;
@@ -2062,14 +2025,20 @@
         break;
     case LYD_TYPE_NOTIF_RESTCONF:
         assert(!parent);
-        rc = lydjson_env_restconf_notif(lydctx->jsonctx, envp, &int_opts, &close_elem);
+
+        /* parse "notification" */
+        rc = lydjson_envelope(lydctx->jsonctx, "notification", "ietf-restconf", envp);
         LY_CHECK_GOTO(rc, cleanup);
+
+        /* RESTCONF notification and eventTime */
+        int_opts = LYD_INTOPT_WITH_SIBLINGS | LYD_INTOPT_NOTIF | LYD_INTOPT_EVENTTIME;
+        close_elem = 1;
         break;
     case LYD_TYPE_REPLY_RESTCONF:
         assert(parent);
 
         /* parse "output" */
-        rc = lydjson_envelope(lydctx->jsonctx, "output", lyd_node_module(parent)->name, 0, envp);
+        rc = lydjson_envelope(lydctx->jsonctx, "output", lyd_node_module(parent)->name, envp);
         LY_CHECK_GOTO(rc, cleanup);
 
         int_opts = LYD_INTOPT_WITH_SIBLINGS | LYD_INTOPT_REPLY;
@@ -2090,38 +2059,41 @@
     do {
         r = lydjson_subtree_r(lydctx, parent, first_p, parsed);
         LY_DPARSER_ERR_GOTO(r, rc = r, lydctx, cleanup);
-
-        status = lyjson_ctx_status(lydctx->jsonctx);
-
-        if (!(int_opts & LYD_INTOPT_WITH_SIBLINGS)) {
-            break;
-        }
-    } while (status == LYJSON_OBJECT_NEXT);
+    } while (lyjson_ctx_status(lydctx->jsonctx) == LYJSON_OBJECT_NEXT);
 
     /* close all opened elements */
     for (i = 0; i < close_elem; ++i) {
-        if (status != LYJSON_OBJECT_CLOSED) {
+        if (lyjson_ctx_status(lydctx->jsonctx) != LYJSON_OBJECT_CLOSED) {
             LOGVAL(ctx, LYVE_SYNTAX_JSON, "Expecting JSON %s but %s found.", lyjson_token2str(LYJSON_OBJECT_CLOSED),
-                    lyjson_token2str(status));
+                    lyjson_token2str(lyjson_ctx_status(lydctx->jsonctx)));
             rc = LY_EVALID;
             goto cleanup;
         }
 
-        r = lyjson_ctx_next(lydctx->jsonctx, &status);
+        r = lyjson_ctx_next(lydctx->jsonctx, NULL);
         LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
     }
 
-    if ((int_opts & LYD_INTOPT_NO_SIBLINGS) && lydctx->jsonctx->in->current[0] &&
-            (lyjson_ctx_status(lydctx->jsonctx) != LYJSON_OBJECT_CLOSED)) {
-        LOGVAL(ctx, LYVE_SYNTAX, "Unexpected sibling node.");
-        r = LY_EVALID;
-        LY_DPARSER_ERR_GOTO(r, rc = r, lydctx, cleanup);
-    }
     if ((int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY)) && !lydctx->op_node) {
         LOGVAL(ctx, LYVE_DATA, "Missing the operation node.");
         r = LY_EVALID;
         LY_DPARSER_ERR_GOTO(r, rc = r, lydctx, cleanup);
     }
+    if (int_opts & LYD_INTOPT_EVENTTIME) {
+        /* parse as a child of the envelope */
+        node = (*first_p)->prev;
+        if (node->schema) {
+            LOGVAL(ctx, LYVE_DATA, "Missing notification \"eventTime\" node.");
+            r = LY_EVALID;
+            LY_DPARSER_ERR_GOTO(r, rc = r, lydctx, cleanup);
+        } else {
+            /* can be the only opaque node and an operation had to be parsed */
+            assert(!strcmp(LYD_NAME(node), "eventTime") && (*first_p)->next);
+            lyd_unlink_tree(node);
+            assert(*envp);
+            lyd_insert_child(*envp, node);
+        }
+    }
 
     /* finish linking metadata */
     r = lydjson_metadata_finish(lydctx, parent ? lyd_node_child_p(parent) : first_p);