tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

messageformat2_data_model.h (98929B)


      1 // © 2024 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 
      4 #include "unicode/utypes.h"
      5 
      6 #ifndef MESSAGEFORMAT_DATA_MODEL_H
      7 #define MESSAGEFORMAT_DATA_MODEL_H
      8 
      9 #if U_SHOW_CPLUSPLUS_API
     10 
     11 #if !UCONFIG_NO_NORMALIZATION
     12 
     13 #if !UCONFIG_NO_FORMATTING
     14 
     15 #if !UCONFIG_NO_MF2
     16 
     17 #include "unicode/localpointer.h"
     18 #include "unicode/messageformat2_data_model_names.h"
     19 
     20 #ifndef U_HIDE_DEPRECATED_API
     21 
     22 #include <algorithm>
     23 #include <cstddef>
     24 #include <iterator>
     25 #include <optional>
     26 #include <variant>
     27 #include <vector>
     28 
     29 U_NAMESPACE_BEGIN
     30 
     31 class UVector;
     32 
     33 // Helpers
     34 
     35 // Note: this _must_ be declared `inline` or else gcc will generate code
     36 // for its instantiations, which needs to be avoided because it returns
     37 // a std::vector
     38 template<typename T>
     39 static inline std::vector<T> toStdVector(const T* arr, int32_t len) {
     40    std::vector<T> result;
     41    for (int32_t i = 0; i < len; i++) {
     42        result.push_back(arr[i]);
     43    }
     44    return result;
     45 }
     46 
     47 #if defined(U_REAL_MSVC)
     48 #pragma warning(push)
     49 // Ignore warning 4251 as these templates are instantiated later in this file,
     50 // after the classes used to instantiate them have been defined.
     51 #pragma warning(disable: 4251)
     52 #endif
     53 
     54 namespace message2 {
     55    class Checker;
     56    class MessageFormatter;
     57    class Parser;
     58    class Serializer;
     59 
     60 
     61  namespace data_model {
     62        class Binding;
     63        class Literal;
     64        class Operator;
     65        class MFDataModel;
     66 
     67      /**
     68         * The `Literal` class corresponds to the `literal` nonterminal in the MessageFormat 2 grammar,
     69         * https://github.com/unicode-org/message-format-wg/blob/main/spec/message.abnf and the
     70         * `Literal` interface defined in
     71         *   // https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#expressions
     72         *
     73         * `Literal` is immutable, copyable and movable.
     74         *
     75         * @internal ICU 75 technology preview
     76         * @deprecated This API is for technology preview only.
     77         */
     78        class U_I18N_API Literal : public UObject {
     79        public:
     80            /**
     81             * Returns the quoted representation of this literal (enclosed in '|' characters)
     82             *
     83             * @return A string representation of the literal enclosed in quote characters.
     84             *
     85             * @internal ICU 75 technology preview
     86             * @deprecated This API is for technology preview only.
     87             */
     88            UnicodeString quoted() const;
     89            /**
     90             * Returns the parsed string contents of this literal.
     91             *
     92             * @return A string representation of this literal.
     93             *
     94             * @internal ICU 75 technology preview
     95             * @deprecated This API is for technology preview only.
     96             */
     97            const UnicodeString& unquoted() const;
     98            /**
     99             * Determines if this literal appeared as a quoted literal in the message.
    100             *
    101             * @return true if and only if this literal appeared as a quoted literal in the
    102             *         message.
    103             *
    104             * @internal ICU 75 technology preview
    105             * @deprecated This API is for technology preview only.
    106             */
    107            UBool isQuoted() const { return thisIsQuoted; }
    108            /**
    109             * Literal constructor.
    110             *
    111             *  @param q True if and only if this literal was parsed with the `quoted` nonterminal
    112             *           (appeared enclosed in '|' characters in the message text).
    113             *  @param s The string contents of this literal; escape sequences are assumed to have
    114             *           been interpreted already.
    115             *
    116             * @internal ICU 75 technology preview
    117             * @deprecated This API is for technology preview only.
    118             */
    119            Literal(UBool q, const UnicodeString& s) : thisIsQuoted(q), contents(s) {}
    120            /**
    121             * Copy constructor.
    122             *
    123             * @internal ICU 75 technology preview
    124             * @deprecated This API is for technology preview only.
    125             */
    126            Literal(const Literal& other) : thisIsQuoted(other.thisIsQuoted), contents(other.contents) {}
    127            /**
    128             * Non-member swap function.
    129             * @param l1 will get l2's contents
    130             * @param l2 will get l1's contents
    131             *
    132             * @internal ICU 75 technology preview
    133             * @deprecated This API is for technology preview only.
    134             */
    135            friend inline void swap(Literal& l1, Literal& l2) noexcept {
    136                using std::swap;
    137 
    138                swap(l1.thisIsQuoted, l2.thisIsQuoted);
    139                swap(l1.contents, l2.contents);
    140            }
    141            /**
    142             * Assignment operator.
    143             *
    144             * @internal ICU 75 technology preview
    145             * @deprecated This API is for technology preview only.
    146             */
    147            Literal& operator=(Literal) noexcept;
    148            /**
    149             * Default constructor.
    150             * Puts the Literal into a valid but undefined state.
    151             *
    152             * @internal ICU 75 technology preview
    153             * @deprecated This API is for technology preview only.
    154             */
    155            Literal() = default;
    156            /**
    157             * Less than operator. Compares `this.stringContents()` with
    158             * `other.stringContents()`. This method is used in representing
    159             * the mapping from key lists to patterns in a message with variants,
    160             * and is not expected to be useful otherwise.
    161             *
    162             * @param other The Literal to compare to this one.
    163             * @return true if the parsed string corresponding to this `Literal`
    164             * is less than the parsed string corresponding to the other `Literal`
    165             * (according to `UnicodeString`'s less-than operator).
    166             * Returns false otherwise.
    167             *
    168             * @internal ICU 75 technology preview
    169             * @deprecated This API is for technology preview only.
    170             */
    171            bool operator<(const Literal& other) const;
    172            /**
    173             * Equality operator. Compares `this.stringContents()` with
    174             * `other.stringContents()`. This method is used in representing
    175             * the mapping from key lists to patterns in a message with variants,
    176             * and is not expected to be useful otherwise.
    177             *
    178             * @param other The Literal to compare to this one.
    179             * @return true if the parsed string corresponding to this `Literal`
    180             * equals the parsed string corresponding to the other `Literal`
    181             * (according to `UnicodeString`'s equality operator).
    182             * Returns false otherwise.
    183             *
    184             * @internal ICU 75 technology preview
    185             * @deprecated This API is for technology preview only.
    186             */
    187            bool operator==(const Literal& other) const;
    188            /**
    189             * Destructor.
    190             *
    191             * @internal ICU 75 technology preview
    192             * @deprecated This API is for technology preview only.
    193             */
    194            virtual ~Literal();
    195 
    196        private:
    197            /* const */ bool thisIsQuoted = false;
    198            /* const */ UnicodeString contents;
    199        };
    200 
    201        /**
    202         * The `Operand` class corresponds to the `operand` nonterminal in the MessageFormat 2 grammar,
    203         * https://github.com/unicode-org/message-format-wg/blob/main/spec/message.abnf .
    204         * It represents a `Literal | VariableRef` -- see the `operand?` field of the `FunctionRef`
    205         * interface defined at:
    206         * https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#expressions
    207         * with the difference that it can also represent a null operand (the absent operand in an
    208         * `annotation` with no operand).
    209         *
    210         * `Operand` is immutable and is copyable and movable.
    211         *
    212         * @internal ICU 75 technology preview
    213         * @deprecated This API is for technology preview only.
    214         */
    215        class U_I18N_API_CLASS Operand : public UObject {
    216        public:
    217            /**
    218             * Determines if this operand represents a variable.
    219             *
    220             * @return True if and only if the operand is a variable.
    221             *
    222             * @internal ICU 75 technology preview
    223             * @deprecated This API is for technology preview only.
    224             */
    225            U_I18N_API UBool isVariable() const;
    226            /**
    227             * Determines if this operand represents a literal.
    228             *
    229             * @return True if and only if the operand is a literal.
    230             *
    231             * @internal ICU 75 technology preview
    232             * @deprecated This API is for technology preview only.
    233             */
    234            U_I18N_API UBool isLiteral() const;
    235            /**
    236             * Determines if this operand is the null operand.
    237             *
    238             * @return True if and only if the operand is the null operand.
    239             *
    240             * @internal ICU 75 technology preview
    241             * @deprecated This API is for technology preview only.
    242             */
    243            U_I18N_API virtual UBool isNull() const;
    244            /**
    245             * Returns a reference to this operand's variable name.
    246             * Precondition: isVariable()
    247             *
    248             * @return A reference to the name of the variable
    249             *
    250             * @internal ICU 75 technology preview
    251             * @deprecated This API is for technology preview only.
    252             */
    253            U_I18N_API const UnicodeString& asVariable() const;
    254            /**
    255             * Returns a reference to this operand's literal contents.
    256             * Precondition: isLiteral()
    257             *
    258             * @return A reference to the literal
    259             *
    260             * @internal ICU 75 technology preview
    261             * @deprecated This API is for technology preview only.
    262             */
    263            U_I18N_API const Literal& asLiteral() const;
    264            /**
    265             * Default constructor.
    266             * Creates a null Operand.
    267             *
    268             * @internal ICU 75 technology preview
    269             * @deprecated This API is for technology preview only.
    270             */
    271            U_I18N_API Operand() : contents(std::nullopt) {}
    272            /**
    273             * Variable operand constructor.
    274             *
    275             * @param v The variable name; an operand corresponding
    276             *        to a reference to `v` is returned.
    277             *
    278             * @internal ICU 75 technology preview
    279             * @deprecated This API is for technology preview only.
    280             */
    281            U_I18N_API explicit Operand(const UnicodeString& v) : contents(VariableName(v)) {}
    282            /**
    283             * Literal operand constructor.
    284             *
    285             * @param l The literal to use for this operand; an operand
    286             *        corresponding to `l` is returned.
    287             *
    288             * @internal ICU 75 technology preview
    289             * @deprecated This API is for technology preview only.
    290             */
    291            U_I18N_API explicit Operand(const Literal& l) : contents(l) {}
    292            /**
    293             * Non-member swap function.
    294             * @param o1 will get o2's contents
    295             * @param o2 will get o1's contents
    296             *
    297             * @internal ICU 75 technology preview
    298             * @deprecated This API is for technology preview only.
    299             */
    300            U_I18N_API friend inline void swap(Operand& o1, Operand& o2) noexcept {
    301                using std::swap;
    302                (void) o1;
    303                (void) o2;
    304                swap(o1.contents, o2.contents);
    305            }
    306            /**
    307             * Assignment operator.
    308             *
    309             * @internal ICU 75 technology preview
    310             * @deprecated This API is for technology preview only.
    311             */
    312            U_I18N_API virtual Operand& operator=(Operand) noexcept;
    313            /**
    314             * Copy constructor.
    315             *
    316             * @internal ICU 75 technology preview
    317             * @deprecated This API is for technology preview only.
    318             */
    319            U_I18N_API Operand(const Operand&);
    320            /**
    321             * Destructor.
    322             *
    323             * @internal ICU 75 technology preview
    324             * @deprecated This API is for technology preview only.
    325             */
    326            U_I18N_API virtual ~Operand();
    327        private:
    328            std::optional<std::variant<VariableName, Literal>> contents;
    329        }; // class Operand
    330 
    331        /**
    332         * The `Key` class corresponds to the `key` nonterminal in the MessageFormat 2 grammar,
    333         * https://github.com/unicode-org/message-format-wg/blob/main/spec/message.abnf .
    334         * It also corresponds to
    335         * the `Literal | CatchallKey` that is the
    336         * element type of the `keys` array in the `Variant` interface
    337         * defined in https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#messages
    338         *
    339         * A key is either a literal or the wildcard symbol (represented in messages as '*')
    340         *
    341         * `Key` is immutable, copyable and movable.
    342         *
    343         * @internal ICU 75 technology preview
    344         * @deprecated This API is for technology preview only.
    345         */
    346        class U_I18N_API_CLASS Key : public UObject {
    347        public:
    348            /**
    349             * Determines if this is a wildcard key
    350             *
    351             * @return True if and only if this is the wildcard key
    352             *
    353             * @internal ICU 75 technology preview
    354             * @deprecated This API is for technology preview only.
    355             */
    356            U_I18N_API UBool isWildcard() const { return !contents.has_value(); }
    357            /**
    358             * Returns the contents of this key as a literal.
    359             * Precondition: !isWildcard()
    360             *
    361             * @return The literal contents of the key
    362             *
    363             * @internal ICU 75 technology preview
    364             * @deprecated This API is for technology preview only.
    365             */
    366            U_I18N_API const Literal& asLiteral() const;
    367            /**
    368             * Copy constructor.
    369             *
    370             * @internal ICU 75 technology preview
    371             * @deprecated This API is for technology preview only.
    372             */
    373            U_I18N_API Key(const Key& other) : contents(other.contents) {}
    374            /**
    375             * Wildcard constructor; constructs a Key representing the
    376             * catchall or wildcard key, '*'.
    377             *
    378             * @internal ICU 75 technology preview
    379             * @deprecated This API is for technology preview only.
    380             */
    381            U_I18N_API Key() : contents(std::nullopt) {}
    382            /**
    383             * Literal key constructor.
    384             *
    385             * @param lit A Literal to use for this key. The result matches the
    386             *        literal `lit`.
    387             *
    388             * @internal ICU 75 technology preview
    389             * @deprecated This API is for technology preview only.
    390             */
    391            U_I18N_API explicit Key(const Literal& lit) : contents(lit) {}
    392            /**
    393             * Non-member swap function.
    394             * @param k1 will get k2's contents
    395             * @param k2 will get k1's contents
    396             *
    397             * @internal ICU 75 technology preview
    398             * @deprecated This API is for technology preview only.
    399             */
    400            U_I18N_API friend inline void swap(Key& k1, Key& k2) noexcept {
    401                using std::swap;
    402 
    403                swap(k1.contents, k2.contents);
    404            }
    405            /**
    406             * Assignment operator
    407             *
    408             * @internal ICU 75 technology preview
    409             * @deprecated This API is for technology preview only.
    410             */
    411            U_I18N_API Key& operator=(Key) noexcept;
    412            /**
    413             * Less than operator. Compares the literal of `this` with the literal of `other`.
    414             * This method is used in representing the mapping from key lists to patterns
    415             * in a message with variants, and is not expected to be useful otherwise.
    416             *
    417             * @param other The Key to compare to this one.
    418             * @return true if the two `Key`s are not wildcards and if `this.asLiteral()`
    419             * < `other.asLiteral()`.
    420             * Returns false otherwise.
    421             *
    422             * @internal ICU 75 technology preview
    423             * @deprecated This API is for technology preview only.
    424             */
    425            U_I18N_API bool operator<(const Key& other) const;
    426            /**
    427             * Equality operator. Compares the literal of `this` with the literal of `other`.
    428             * This method is used in representing the mapping from key lists to patterns
    429             * in a message with variants, and is not expected to be useful otherwise.
    430             *
    431             * @param other The Key to compare to this one.
    432             * @return true if either both `Key`s are wildcards, or `this.asLiteral()`
    433             * == `other.asLiteral()`.
    434             * Returns false otherwise.
    435             *
    436             * @internal ICU 75 technology preview
    437             * @deprecated This API is for technology preview only.
    438             */
    439            U_I18N_API bool operator==(const Key& other) const;
    440            /**
    441             * Destructor.
    442             *
    443             * @internal ICU 75 technology preview
    444             * @deprecated This API is for technology preview only.
    445             */
    446            U_I18N_API virtual ~Key();
    447        private:
    448            /* const */ std::optional<Literal> contents;
    449        }; // class Key
    450 
    451        /**
    452         * The `SelectorKeys` class represents the key list for a single variant.
    453         * It corresponds to the `keys` array in the `Variant` interface
    454         * defined in https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#messages
    455         *
    456         * `SelectorKeys` is immutable, copyable and movable.
    457         *
    458         * @internal ICU 75 technology preview
    459         * @deprecated This API is for technology preview only.
    460         */
    461        class U_I18N_API_CLASS SelectorKeys : public UObject {
    462        public:
    463            /**
    464             * Returns the underlying list of keys.
    465             *
    466             * @return The list of keys for this variant.
    467             *         Returns an empty list if allocating this `SelectorKeys`
    468             *         object previously failed.
    469             *
    470             * @internal ICU 75 technology preview
    471             * @deprecated This API is for technology preview only.
    472             */
    473            U_I18N_API std::vector<Key> getKeys() const {
    474                return toStdVector<Key>(keys.getAlias(), len);
    475            }
    476            /**
    477             * The mutable `SelectorKeys::Builder` class allows the key list to be constructed
    478             * one key at a time.
    479             *
    480             * Builder is not copyable or movable.
    481             *
    482             * @internal ICU 75 technology preview
    483             * @deprecated This API is for technology preview only.
    484             */
    485            class U_I18N_API Builder : public UMemory {
    486            private:
    487                friend class SelectorKeys;
    488                UVector* keys; // This is a raw pointer and not a LocalPointer<UVector> to avoid undefined behavior warnings,
    489                               // since UVector is forward-declared
    490                               // The vector owns its elements
    491            public:
    492                /**
    493                 * Adds a single key to the list.
    494                 *
    495                 * @param key    The key to be added. Passed by move
    496                 * @param status Input/output error code
    497                 * @return A reference to the builder.
    498                 *
    499                 * @internal ICU 75 technology preview
    500                 * @deprecated This API is for technology preview only.
    501                 */
    502                Builder& add(Key&& key, UErrorCode& status) noexcept;
    503                /**
    504                 * Constructs a new immutable `SelectorKeys` using the list of keys
    505                 * set with previous `add()` calls.
    506                 *
    507                 * The builder object (`this`) can still be used after calling `build()`.
    508                 *
    509                 * @param status    Input/output error code
    510                 * @return          The new SelectorKeys object
    511                 *
    512                 * @internal ICU 75 technology preview
    513                 * @deprecated This API is for technology preview only.
    514                 */
    515                SelectorKeys build(UErrorCode& status) const;
    516                /**
    517                 * Default constructor.
    518                 * Returns a Builder with an empty list of keys.
    519                 *
    520                 * @param status Input/output error code
    521                 *
    522                 * @internal ICU 75 technology preview
    523                 * @deprecated This API is for technology preview only.
    524                 */
    525                Builder(UErrorCode& status);
    526                /**
    527                 * Destructor.
    528                 *
    529                 * @internal ICU 75 technology preview
    530                 * @deprecated This API is for technology preview only.
    531                 */
    532                virtual ~Builder();
    533                Builder(const Builder&) = delete;
    534                Builder& operator=(const Builder&) = delete;
    535                Builder(Builder&&) = delete;
    536                Builder& operator=(Builder&&) = delete;
    537            }; // class SelectorKeys::Builder
    538            /**
    539             * Less than operator. Compares the two key lists lexicographically.
    540             * This method makes it possible for a `SelectorKeys` to be used as a map
    541             * key, which allows variants to be represented as a map. It is not expected
    542             * to be useful otherwise.
    543             *
    544             * @param other The SelectorKeys to compare to this one.
    545             * @return true if `this` is less than `other`, comparing the two key lists
    546             * lexicographically.
    547             * Returns false otherwise.
    548             *
    549             * @internal ICU 75 technology preview
    550             * @deprecated This API is for technology preview only.
    551             */
    552            U_I18N_API bool operator<(const SelectorKeys& other) const;
    553            /**
    554             * Default constructor.
    555             * Puts the SelectorKeys into a valid but undefined state.
    556             *
    557             * @internal ICU 75 technology preview
    558             * @deprecated This API is for technology preview only.
    559             */
    560            U_I18N_API SelectorKeys() : len(0) {}
    561            /**
    562             * Non-member swap function.
    563             * @param s1 will get s2's contents
    564             * @param s2 will get s1's contents
    565             *
    566             * @internal ICU 75 technology preview
    567             * @deprecated This API is for technology preview only.
    568             */
    569            U_I18N_API friend inline void swap(SelectorKeys& s1, SelectorKeys& s2) noexcept {
    570                using std::swap;
    571 
    572                swap(s1.len, s2.len);
    573                swap(s1.keys, s2.keys);
    574            }
    575            /**
    576             * Copy constructor.
    577             *
    578             * @internal ICU 75 technology preview
    579             * @deprecated This API is for technology preview only.
    580             */
    581            U_I18N_API SelectorKeys(const SelectorKeys& other);
    582            /**
    583             * Assignment operator.
    584             *
    585             * @internal ICU 75 technology preview
    586             * @deprecated This API is for technology preview only.
    587             */
    588            U_I18N_API SelectorKeys& operator=(SelectorKeys other) noexcept;
    589            /**
    590             * Destructor.
    591             *
    592             * @internal ICU 75 technology preview
    593             * @deprecated This API is for technology preview only.
    594             */
    595            U_I18N_API virtual ~SelectorKeys();
    596        private:
    597            friend class Builder;
    598            friend class message2::Checker;
    599            friend class message2::MessageFormatter;
    600            friend class message2::Serializer;
    601 
    602            /* const */ LocalArray<Key> keys;
    603            /* const */ int32_t len;
    604 
    605            const Key* getKeysInternal() const;
    606            SelectorKeys(const UVector& ks, UErrorCode& status);
    607        }; // class SelectorKeys
    608 
    609        class Operator;
    610 
    611        /**
    612         *  An `Option` pairs an option name with an Operand.
    613         *
    614         * `Option` is immutable, copyable and movable.
    615         *
    616         * @internal ICU 75 technology preview
    617         * @deprecated This API is for technology preview only.
    618         */
    619        class U_I18N_API Option : public UObject {
    620        public:
    621            /**
    622             * Accesses the right-hand side of the option.
    623             *
    624             * @return A reference to the operand.
    625             *
    626             * @internal ICU 75 technology preview
    627             * @deprecated This API is for technology preview only.
    628             */
    629            const Operand& getValue() const { return rand; }
    630            /**
    631             * Accesses the left-hand side of the option.
    632             *
    633             * @return A reference to the option name.
    634             *
    635             * @internal ICU 75 technology preview
    636             * @deprecated This API is for technology preview only.
    637             */
    638            const UnicodeString& getName() const { return name; }
    639            /**
    640             * Constructor. Returns an `Option` representing the
    641             * named option "name=rand".
    642             *
    643             * @param n The name of the option.
    644             * @param r The value of the option.
    645             *
    646             * @internal ICU 75 technology preview
    647             * @deprecated This API is for technology preview only.
    648             */
    649            Option(const UnicodeString& n, Operand&& r) : name(n), rand(std::move(r)) {}
    650            /**
    651             * Default constructor.
    652             * Returns an Option in a valid but undefined state.
    653             *
    654             * @internal ICU 75 technology preview
    655             * @deprecated This API is for technology preview only.
    656             */
    657            Option() {}
    658            /**
    659             * Non-member swap function.
    660             * @param o1 will get o2's contents
    661             * @param o2 will get o1's contents
    662             *
    663             * @internal ICU 75 technology preview
    664             * @deprecated This API is for technology preview only.
    665             */
    666            friend inline void swap(Option& o1, Option& o2) noexcept {
    667                using std::swap;
    668 
    669                swap(o1.name, o2.name);
    670                swap(o1.rand, o2.rand);
    671            }
    672            /**
    673             * Copy constructor.
    674             *
    675             * @internal ICU 75 technology preview
    676             * @deprecated This API is for technology preview only.
    677             */
    678            Option(const Option& other);
    679            /**
    680             * Assignment operator
    681             *
    682             * @internal ICU 75 technology preview
    683             * @deprecated This API is for technology preview only.
    684             */
    685            Option& operator=(Option other) noexcept;
    686            /**
    687             * Destructor.
    688             *
    689             * @internal ICU 75 technology preview
    690             * @deprecated This API is for technology preview only.
    691             */
    692            virtual ~Option();
    693        private:
    694            /* const */ UnicodeString name;
    695            /* const */ Operand rand;
    696        }; // class Option
    697 
    698        // Internal only
    699        #ifndef U_IN_DOXYGEN
    700        // Options
    701        // This is a wrapper class around a vector of options that provides lookup operations
    702        class U_I18N_API_CLASS OptionMap : public UObject {
    703        public:
    704            U_I18N_API int32_t size() const;
    705            // Needs to take an error code b/c an earlier copy might have failed
    706            U_I18N_API const Option& getOption(int32_t, UErrorCode&) const;
    707            U_I18N_API friend inline void swap(OptionMap& m1, OptionMap& m2) noexcept {
    708                using std::swap;
    709 
    710                swap(m1.bogus, m2.bogus);
    711                swap(m1.options, m2.options);
    712                swap(m1.len, m2.len);
    713            }
    714            U_I18N_API OptionMap() : len(0) {}
    715            U_I18N_API OptionMap(const OptionMap&);
    716            U_I18N_API OptionMap& operator=(OptionMap);
    717            U_I18N_API std::vector<Option> getOptions() const {
    718                return toStdVector<Option>(options.getAlias(), len);
    719            }
    720            U_I18N_API OptionMap(const UVector&, UErrorCode&);
    721            U_I18N_API OptionMap(Option*, int32_t);
    722            U_I18N_API virtual ~OptionMap();
    723 
    724            class U_I18N_API Builder : public UObject {
    725                private:
    726                    UVector* options;
    727                    bool checkDuplicates = true;
    728                public:
    729                    Builder& add(Option&& opt, UErrorCode&);
    730                    Builder(UErrorCode&);
    731                    static Builder attributes(UErrorCode&);
    732                    // As this class is private, build() is destructive
    733                    OptionMap build(UErrorCode&);
    734 	    friend inline void swap(Builder& m1, Builder& m2) noexcept {
    735 	      using std::swap;
    736 
    737 	      swap(m1.options, m2.options);
    738 	      swap(m1.checkDuplicates, m2.checkDuplicates);
    739 	    }
    740 	    Builder(Builder&&);
    741 	    Builder(const Builder&) = delete;
    742 	    Builder& operator=(Builder) noexcept;
    743 	    virtual ~Builder();
    744            }; // class OptionMap::Builder
    745        private:
    746            friend class message2::Serializer;
    747 
    748            bool bogus = false;
    749            LocalArray<Option> options;
    750            int32_t len;
    751        }; // class OptionMap
    752        #endif
    753 
    754        /**
    755         * The `Operator` class corresponds to the `FunctionRef` type in the
    756         * `Expression` interface defined in
    757         * https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#patterns
    758         *
    759         * It represents the annotation that an expression can have: a function name paired
    760         * with a map from option names to operands (possibly empty).
    761         *
    762         * `Operator` is immutable, copyable and movable.
    763         *
    764         * @internal ICU 75 technology preview
    765         * @deprecated This API is for technology preview only.
    766         */
    767        class U_I18N_API Operator : public UObject {
    768        public:
    769            /**
    770             * Accesses the function name.
    771             *
    772             * @return The function name of this operator.
    773             *
    774             * @internal ICU 75 technology preview
    775             * @deprecated This API is for technology preview only.
    776             */
    777            const FunctionName& getFunctionName() const;
    778            /**
    779             * Accesses function options.
    780             *
    781             * @return A vector of function options for this operator.
    782             *
    783             * @internal ICU 75 technology preview
    784             * @deprecated This API is for technology preview only.
    785             */
    786            std::vector<Option> getOptions() const {
    787                return options.getOptions();
    788            }
    789            /**
    790             * The mutable `Operator::Builder` class allows the operator to be constructed
    791             * incrementally.
    792             *
    793             * Builder is not copyable or movable.
    794             *
    795             * @internal ICU 75 technology preview
    796             * @deprecated This API is for technology preview only.
    797             */
    798            class U_I18N_API Builder : public UMemory {
    799            private:
    800                friend class Operator;
    801                FunctionName functionName;
    802                OptionMap::Builder options;
    803            public:
    804                /**
    805                 * Sets this operator to be a function annotation and sets its name
    806                 * to `func`.
    807                 *
    808                 * @param func The function name.
    809                 * @return A reference to the builder.
    810                 *
    811                 * @internal ICU 75 technology preview
    812                 * @deprecated This API is for technology preview only.
    813                 */
    814                Builder& setFunctionName(FunctionName&& func);
    815                /**
    816                 * Sets this operator to be a function annotation and adds a
    817                 * single option.
    818                 *
    819                 * @param key The name of the option.
    820                 * @param value The value (right-hand side) of the option.
    821                 * @param status Input/output error code.
    822                 * @return A reference to the builder.
    823                 *
    824                 * @internal ICU 75 technology preview
    825                 * @deprecated This API is for technology preview only.
    826                 */
    827                Builder& addOption(const UnicodeString &key, Operand&& value, UErrorCode& status) noexcept;
    828                /**
    829                 * Constructs a new immutable `Operator` using the
    830                 * function name and options that were previously set.
    831                 *
    832                 * The builder object (`this`) can still be used after calling `build()`.
    833                 *
    834                 * The `build()` method is non-const for internal implementation reasons,
    835                 * but is observably const.
    836                 *
    837                 * @param status    Input/output error code.
    838                 * @return          The new Operator
    839                 *
    840                 * @internal ICU 75 technology preview
    841                 * @deprecated This API is for technology preview only.
    842                 */
    843                Operator build(UErrorCode& status);
    844                /**
    845                 * Default constructor.
    846                 * Returns a Builder with no function name or options set.
    847                 *
    848                 * @param status    Input/output error code.
    849                 *
    850                 * @internal ICU 75 technology preview
    851                 * @deprecated This API is for technology preview only.
    852                 */
    853                Builder(UErrorCode& status);
    854                /**
    855                 * Destructor.
    856                 *
    857                 * @internal ICU 75 technology preview
    858                 * @deprecated This API is for technology preview only.
    859                 */
    860                virtual ~Builder();
    861                Builder(const Builder&) = delete;
    862                Builder& operator=(const Builder&) = delete;
    863                Builder(Builder&&) = delete;
    864                Builder& operator=(Builder&&) = delete;
    865            }; // class Operator::Builder
    866            /**
    867             * Copy constructor.
    868             *
    869             * @internal ICU 75 technology preview
    870             * @deprecated This API is for technology preview only.
    871             */
    872            Operator(const Operator& other) noexcept;
    873            /**
    874             * Non-member swap function.
    875             * @param o1 will get o2's contents
    876             * @param o2 will get o1's contents
    877             *
    878             * @internal ICU 75 technology preview
    879             * @deprecated This API is for technology preview only.
    880             */
    881            friend inline void swap(Operator& o1, Operator& o2) noexcept {
    882                using std::swap;
    883 
    884                swap(o1.name, o2.name);
    885                swap(o1.options, o2.options);
    886            }
    887            /**
    888             * Assignment operator.
    889             *
    890             * @internal ICU 75 technology preview
    891             * @deprecated This API is for technology preview only.
    892             */
    893            Operator& operator=(Operator) noexcept;
    894            /**
    895             * Default constructor.
    896             * Puts the Operator into a valid but undefined state.
    897             *
    898             * @internal ICU 75 technology preview
    899             * @deprecated This API is for technology preview only.
    900             */
    901            Operator() {}
    902            /**
    903             * Destructor.
    904             *
    905             * @internal ICU 75 technology preview
    906             * @deprecated This API is for technology preview only.
    907             */
    908            virtual ~Operator();
    909        private:
    910            friend class Binding;
    911            friend class Builder;
    912            friend class message2::Checker;
    913            friend class message2::MessageFormatter;
    914            friend class message2::Serializer;
    915 
    916            // Function call constructor
    917            Operator(const FunctionName& f, const UVector& options, UErrorCode&);
    918 
    919            const OptionMap& getOptionsInternal() const;
    920            Operator(const FunctionName&, const OptionMap&);
    921 
    922            /* const */ FunctionName name;
    923            /* const */ OptionMap options;
    924        }; // class Operator
    925 
    926      // Internal only
    927      typedef enum UMarkupType {
    928          UMARKUP_OPEN = 0,
    929          UMARKUP_CLOSE,
    930          UMARKUP_STANDALONE,
    931          UMARKUP_COUNT
    932      } UMarkupType;
    933 
    934      /**
    935         * The `Markup` class corresponds to the `markup` nonterminal in the MessageFormat 2
    936         * grammar and the `markup` interface defined in
    937         * https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model/message.json
    938         *
    939         * `Markup` is immutable, copyable and movable.
    940         *
    941         * @internal ICU 75 technology preview
    942         * @deprecated This API is for technology preview only.
    943         */
    944        class U_I18N_API Markup : public UObject {
    945        public:
    946            /**
    947             * Checks if this markup is an opening tag.
    948             *
    949             * @return True if and only if this represents an opening tag.
    950             *
    951             * @internal ICU 75 technology preview
    952             * @deprecated This API is for technology preview only.
    953             */
    954            UBool isOpen() const { return (type == UMARKUP_OPEN); }
    955            /**
    956             * Checks if this markup is an closing tag.
    957             *
    958             * @return True if and only if this represents an closing tag.
    959             *
    960             * @internal ICU 75 technology preview
    961             * @deprecated This API is for technology preview only.
    962             */
    963            UBool isClose() const { return (type == UMARKUP_CLOSE); }
    964            /**
    965             * Checks if this markup is an standalone tag.
    966             *
    967             * @return True if and only if this represents a standalone tag.
    968             *
    969             * @internal ICU 75 technology preview
    970             * @deprecated This API is for technology preview only.
    971             */
    972            UBool isStandalone() const { return (type == UMARKUP_STANDALONE); }
    973            /**
    974             * Gets the name of this markup
    975             *
    976             * @return A reference to the string identifying the markup
    977             *
    978             * @internal ICU 75 technology preview
    979             * @deprecated This API is for technology preview only.
    980             */
    981            const UnicodeString& getName() const { return name; }
    982            /**
    983             * Gets the options of this markup
    984             *
    985             * @return A reference to the string identifying the markup
    986             *
    987             * @internal ICU 75 technology preview
    988             * @deprecated This API is for technology preview only.
    989             */
    990            std::vector<Option> getOptions() const { return options.getOptions(); }
    991            /**
    992             * Gets the attributes of this markup
    993             *
    994             * @return A vector of attributes
    995             *
    996             * @internal ICU 75 technology preview
    997             * @deprecated This API is for technology preview only.
    998             */
    999            std::vector<Option> getAttributes() const { return attributes.getOptions(); }
   1000            /**
   1001             * Default constructor.
   1002             * Puts the Markup into a valid but undefined state.
   1003             *
   1004             * @internal ICU 75 technology preview
   1005             * @deprecated This API is for technology preview only.
   1006             */
   1007            Markup() {}
   1008            /**
   1009             * Destructor.
   1010             *
   1011             * @internal ICU 75 technology preview
   1012             * @deprecated This API is for technology preview only.
   1013             */
   1014            virtual ~Markup();
   1015            /**
   1016             * The mutable `Markup::Builder` class allows the markup to be constructed
   1017             * incrementally.
   1018             *
   1019             * Builder is not copyable or movable.
   1020             *
   1021             * @internal ICU 75 technology preview
   1022             * @deprecated This API is for technology preview only.
   1023             */
   1024            class U_I18N_API Builder : public UMemory {
   1025            private:
   1026                friend class Markup;
   1027 
   1028                UnicodeString name;
   1029                OptionMap::Builder options;
   1030                OptionMap::Builder attributes;
   1031                UMarkupType type = UMARKUP_COUNT;
   1032            public:
   1033                /**
   1034                 * Sets the name of this markup.
   1035                 *
   1036                 * @param n A string representing the name.
   1037                 * @return A reference to the builder.
   1038                 *
   1039                 * @internal ICU 75 technology preview
   1040                 * @deprecated This API is for technology preview only.
   1041                 */
   1042                Builder& setName(const UnicodeString& n) { name = n; return *this; }
   1043                /**
   1044                 * Sets this to be an opening markup.
   1045                 *
   1046                 * @return A reference to the builder.
   1047                 *
   1048                 * @internal ICU 75 technology preview
   1049                 * @deprecated This API is for technology preview only.
   1050                 */
   1051                Builder& setOpen() { type = UMARKUP_OPEN; return *this; }
   1052                /**
   1053                 * Sets this to be an closing markup.
   1054                 *
   1055                 * @return A reference to the builder.
   1056                 *
   1057                 * @internal ICU 75 technology preview
   1058                 * @deprecated This API is for technology preview only.
   1059                 */
   1060                Builder& setClose() { type = UMARKUP_CLOSE; return *this; }
   1061                /**
   1062                 * Sets this to be a standalone markup.
   1063                 *
   1064                 * @return A reference to the builder.
   1065                 *
   1066                 * @internal ICU 75 technology preview
   1067                 * @deprecated This API is for technology preview only.
   1068                 */
   1069                Builder& setStandalone() { type = UMARKUP_STANDALONE; return *this; }
   1070                /**
   1071                 * Adds a single option.
   1072                 *
   1073                 * @param key The name of the option.
   1074                 * @param value The value (right-hand side) of the option.
   1075                 * @param status Input/output error code.
   1076                 * @return A reference to the builder.
   1077                 *
   1078                 * @internal ICU 75 technology preview
   1079                 * @deprecated This API is for technology preview only.
   1080                 */
   1081                Builder& addOption(const UnicodeString &key, Operand&& value, UErrorCode& status);
   1082                /**
   1083                 * Adds a single attribute.
   1084                 *
   1085                 * @param key The name of the attribute.
   1086                 * @param value The value (right-hand side) of the attribute.
   1087                 * @param status Input/output error code.
   1088                 * @return A reference to the builder.
   1089                 *
   1090                 * @internal ICU 75 technology preview
   1091                 * @deprecated This API is for technology preview only.
   1092                 */
   1093                Builder& addAttribute(const UnicodeString &key, Operand&& value, UErrorCode& status);
   1094                /**
   1095                 * Constructs a new immutable `Markup` using the name and type
   1096                 * and (optionally) options and attributes that were previously set.
   1097                 * If `setName()` and at least one of `setOpen()`, `setClose()`, and `setStandalone()`
   1098                 * were not previously called,
   1099                 * then `status` is set to U_INVALID_STATE_ERROR.
   1100                 *
   1101                 * The builder object (`this`) can still be used after calling `build()`.
   1102                 * The `build()` method is non-const for internal implementation reasons,
   1103                 * but is observably const.
   1104                 *
   1105                 * @param status    Input/output error code.
   1106                 * @return          The new Markup.
   1107                 *
   1108                 * @internal ICU 75 technology preview
   1109                 * @deprecated This API is for technology preview only.
   1110                 */
   1111                Markup build(UErrorCode& status);
   1112                /**
   1113                 * Default constructor.
   1114                 * Returns a Builder with no name, type, options, or attributes set.
   1115                 *
   1116                 * @param status    Input/output error code.
   1117                 *
   1118                 * @internal ICU 75 technology preview
   1119                 * @deprecated This API is for technology preview only.
   1120                 */
   1121                Builder(UErrorCode& status);
   1122                /**
   1123                 * Destructor.
   1124                 *
   1125                 * @internal ICU 75 technology preview
   1126                 * @deprecated This API is for technology preview only.
   1127                 */
   1128                virtual ~Builder();
   1129                Builder(const Builder&) = delete;
   1130                Builder& operator=(const Builder&) = delete;
   1131                Builder(Builder&&) = delete;
   1132                Builder& operator=(Builder&&) = delete;
   1133            }; // class Markup::Builder
   1134 
   1135        private:
   1136            friend class Builder;
   1137            friend class message2::Serializer;
   1138 
   1139            UMarkupType type;
   1140            UnicodeString name;
   1141            OptionMap options;
   1142            OptionMap attributes;
   1143            const OptionMap& getOptionsInternal() const { return options; }
   1144            const OptionMap& getAttributesInternal() const { return attributes; }
   1145            Markup(UMarkupType, UnicodeString, OptionMap&&, OptionMap&&);
   1146        }; // class Markup
   1147 
   1148        /**
   1149         * The `Expression` class corresponds to the `expression` nonterminal in the MessageFormat 2
   1150         * grammar and the `Expression` interface defined in
   1151         * https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#patterns
   1152         *
   1153         * It represents either an operand with no annotation; an annotation with no operand;
   1154         * or an operand annotated with an annotation.
   1155         *
   1156         * `Expression` is immutable, copyable and movable.
   1157         *
   1158         * @internal ICU 75 technology preview
   1159         * @deprecated This API is for technology preview only.
   1160         */
   1161        class U_I18N_API_CLASS Expression : public UObject {
   1162        public:
   1163            /**
   1164             * Checks if this expression is an annotation
   1165             * with no operand.
   1166             *
   1167             * @return True if and only if the expression has
   1168             *         an annotation and has no operand.
   1169             *
   1170             * @internal ICU 75 technology preview
   1171             * @deprecated This API is for technology preview only.
   1172             */
   1173            U_I18N_API UBool isStandaloneAnnotation() const;
   1174            /**
   1175             * Checks if this expression has a function
   1176             * annotation (with or without an operand).
   1177             *
   1178             * @return True if and only if the expression has an annotation
   1179             *         that is a function.
   1180             *
   1181             * @internal ICU 75 technology preview
   1182             * @deprecated This API is for technology preview only.
   1183             */
   1184            U_I18N_API UBool isFunctionCall() const;
   1185            /**
   1186             * Accesses the function
   1187             * annotating this expression.
   1188             * If !(isFunctionCall()), sets
   1189             * `status` to U_INVALID_STATE_ERROR.
   1190             *
   1191             * @param status Input/output error code.
   1192             * @return A non-owned pointer to the operator of this expression,
   1193             *         which does not outlive the expression.
   1194             *
   1195             * @internal ICU 75 technology preview
   1196             * @deprecated This API is for technology preview only.
   1197             */
   1198            U_I18N_API const Operator* getOperator(UErrorCode& status) const;
   1199            /**
   1200             * Accesses the operand of this expression.
   1201             *
   1202             * @return A reference to the operand of this expression,
   1203             *         which may be the null operand.
   1204             *
   1205             * @internal ICU 75 technology preview
   1206             * @deprecated This API is for technology preview only.
   1207             */
   1208            U_I18N_API const Operand& getOperand() const;
   1209            /**
   1210             * Gets the attributes of this expression
   1211             *
   1212             * @return A vector of attributes
   1213             *
   1214             * @internal ICU 75 technology preview
   1215             * @deprecated This API is for technology preview only.
   1216             */
   1217            U_I18N_API std::vector<Option> getAttributes() const { return attributes.getOptions(); }
   1218            /**
   1219             * The mutable `Expression::Builder` class allows the operator to be constructed
   1220             * incrementally.
   1221             *
   1222             * Builder is not copyable or movable.
   1223             *
   1224             * @internal ICU 75 technology preview
   1225             * @deprecated This API is for technology preview only.
   1226             */
   1227            class U_I18N_API Builder : public UMemory {
   1228            private:
   1229                friend class Expression;
   1230 
   1231                bool hasOperand = false;
   1232                bool hasOperator = false;
   1233                Operand rand;
   1234                Operator rator;
   1235                OptionMap::Builder attributes;
   1236            public:
   1237                /**
   1238                 * Sets the operand of this expression.
   1239                 *
   1240                 * @param rAnd The operand to set. Passed by move.
   1241                 * @return A reference to the builder.
   1242                 *
   1243                 * @internal ICU 75 technology preview
   1244                 * @deprecated This API is for technology preview only.
   1245                 */
   1246                Builder& setOperand(Operand&& rAnd);
   1247                /**
   1248                 * Sets the operator of this expression.
   1249                 *
   1250                 * @param rAtor The operator to set. Passed by move.
   1251                 * @return A reference to the builder.
   1252                 *
   1253                 * @internal ICU 75 technology preview
   1254                 * @deprecated This API is for technology preview only.
   1255                 */
   1256                Builder& setOperator(Operator&& rAtor);
   1257                /**
   1258                 * Adds a single attribute.
   1259                 *
   1260                 * @param key The name of the attribute.
   1261                 * @param value The value (right-hand side) of the attribute.
   1262                 * @param status Input/output error code.
   1263                 * @return A reference to the builder.
   1264                 *
   1265                 * @internal ICU 75 technology preview
   1266                 * @deprecated This API is for technology preview only.
   1267                 */
   1268                Builder& addAttribute(const UnicodeString &key, Operand&& value, UErrorCode& status);
   1269                /**
   1270                 * Constructs a new immutable `Expression` using the operand and operator that
   1271                 * were previously set. If neither `setOperand()` nor `setOperator()` was
   1272                 * previously called, or if `setOperand()` was called with the null operand
   1273                 * and `setOperator()` was never called, then `status` is set to
   1274                 * U_INVALID_STATE_ERROR.
   1275                 *
   1276                 * The builder object (`this`) can still be used after calling `build()`.
   1277                 * The `build()` method is non-const for internal implementation reasons,
   1278                 * but is observably const.
   1279 
   1280                 * @param status    Input/output error code.
   1281                 * @return          The new Expression.
   1282                 *
   1283                 * @internal ICU 75 technology preview
   1284                 * @deprecated This API is for technology preview only.
   1285                 */
   1286                Expression build(UErrorCode& status);
   1287                /**
   1288                 * Default constructor.
   1289                 * Returns a Builder with no operator or operand set.
   1290                 *
   1291                 * @param status    Input/output error code.
   1292                 *
   1293                 * @internal ICU 75 technology preview
   1294                 * @deprecated This API is for technology preview only.
   1295                 */
   1296                Builder(UErrorCode& status);
   1297                /**
   1298                 * Destructor.
   1299                 *
   1300                 * @internal ICU 75 technology preview
   1301                 * @deprecated This API is for technology preview only.
   1302                 */
   1303                virtual ~Builder();
   1304                Builder(const Builder&) = delete;
   1305                Builder& operator=(const Builder&) = delete;
   1306                Builder(Builder&&) = delete;
   1307                Builder& operator=(Builder&&) = delete;
   1308            }; // class Expression::Builder
   1309            /**
   1310             * Non-member swap function.
   1311             * @param e1 will get e2's contents
   1312             * @param e2 will get e1's contents
   1313             *
   1314             * @internal ICU 75 technology preview
   1315             * @deprecated This API is for technology preview only.
   1316             */
   1317            U_I18N_API friend inline void swap(Expression& e1, Expression& e2) noexcept {
   1318                using std::swap;
   1319 
   1320                swap(e1.rator, e2.rator);
   1321                swap(e1.rand, e2.rand);
   1322                swap(e1.attributes, e2.attributes);
   1323            }
   1324            /**
   1325             * Copy constructor.
   1326             *
   1327             * @internal ICU 75 technology preview
   1328             * @deprecated This API is for technology preview only.
   1329             */
   1330            U_I18N_API Expression(const Expression& other);
   1331            /**
   1332             * Assignment operator.
   1333             *
   1334             * @internal ICU 75 technology preview
   1335             * @deprecated This API is for technology preview only.
   1336             */
   1337            U_I18N_API Expression& operator=(Expression) noexcept;
   1338            /**
   1339             * Default constructor.
   1340             * Puts the Expression into a valid but undefined state.
   1341             *
   1342             * @internal ICU 75 technology preview
   1343             * @deprecated This API is for technology preview only.
   1344             */
   1345            U_I18N_API Expression();
   1346            /**
   1347             * Destructor.
   1348             *
   1349             * @internal ICU 75 technology preview
   1350             * @deprecated This API is for technology preview only.
   1351             */
   1352            U_I18N_API virtual ~Expression();
   1353        private:
   1354            friend class message2::Serializer;
   1355 
   1356            /*
   1357              Internally, an expression is represented as the application of an optional operator to an operand.
   1358              The operand is always present; for function calls with no operand, it's represented
   1359              as an operand for which `isNull()` is true.
   1360 
   1361              Operator               | Operand
   1362              --------------------------------
   1363              { |42| :fun opt=value } =>  (FunctionName=fun,     | Literal(quoted=true, contents="42")
   1364              options={opt: value})
   1365              { abcd }                =>  null                   | Literal(quoted=false, contents="abcd")
   1366              { : fun opt=value }     =>  (FunctionName=fun,
   1367              options={opt: value})  | NullOperand()
   1368            */
   1369 
   1370            Expression(const Operator &rAtor, const Operand &rAnd, const OptionMap& attrs) : rator(rAtor), rand(rAnd), attributes(attrs) {}
   1371            Expression(const Operand &rAnd, const OptionMap& attrs) : rator(std::nullopt), rand(Operand(rAnd)), attributes(attrs) {}
   1372            Expression(const Operator &rAtor, const OptionMap& attrs) : rator(rAtor), rand(), attributes(attrs) {}
   1373            /* const */ std::optional<Operator> rator;
   1374            /* const */ Operand rand;
   1375            /* const */ OptionMap attributes;
   1376            const OptionMap& getAttributesInternal() const { return attributes; }
   1377        }; // class Expression
   1378 
   1379      class Pattern;
   1380 
   1381  // Despite the comments, `PatternPart` is internal-only
   1382       /**
   1383         *  A `PatternPart` is a single element (text or expression) in a `Pattern`.
   1384         * It corresponds to the `body` field of the `Pattern` interface
   1385         *  defined in https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#patterns
   1386         *
   1387         * `PatternPart` is immutable, copyable and movable.
   1388         *
   1389         * @internal ICU 75 technology preview
   1390         * @deprecated This API is for technology preview only.
   1391         */
   1392        class U_I18N_API_CLASS PatternPart : public UObject {
   1393        public:
   1394            /**
   1395             * Checks if the part is a text part.
   1396             *
   1397             * @return True if and only if this is a text part.
   1398             *
   1399             * @internal ICU 75 technology preview
   1400             * @deprecated This API is for technology preview only.
   1401             */
   1402            U_I18N_API UBool isText() const { return std::holds_alternative<UnicodeString>(piece); }
   1403            /**
   1404             * Checks if the part is a markup part.
   1405             *
   1406             * @return True if and only if this is a markup part.
   1407             *
   1408             * @internal ICU 75 technology preview
   1409             * @deprecated This API is for technology preview only.
   1410             */
   1411            U_I18N_API UBool isMarkup() const { return std::holds_alternative<Markup>(piece); }
   1412            /**
   1413             * Checks if the part is an expression part.
   1414             *
   1415             * @return True if and only if this is an expression part.
   1416             *
   1417             * @internal ICU 75 technology preview
   1418             * @deprecated This API is for technology preview only.
   1419             */
   1420            U_I18N_API UBool isExpression() const { return std::holds_alternative<Expression>(piece); }
   1421            /**
   1422             * Accesses the expression of the part.
   1423             * Precondition: isExpression()
   1424             *
   1425             * @return A reference to the part's underlying expression.
   1426             *
   1427             * @internal ICU 75 technology preview
   1428             * @deprecated This API is for technology preview only.
   1429             */
   1430            U_I18N_API const Expression& contents() const;
   1431            /**
   1432             * Accesses the expression of the part.
   1433             * Precondition: isMarkup()
   1434             *
   1435             * @return A reference to the part's underlying expression.
   1436             *
   1437             * @internal ICU 75 technology preview
   1438             * @deprecated This API is for technology preview only.
   1439             */
   1440            U_I18N_API const Markup& asMarkup() const;
   1441            /**
   1442             * Accesses the text contents of the part.
   1443             * Precondition: isText()
   1444             *
   1445             * @return A reference to a string representing the part's text..
   1446             *
   1447             * @internal ICU 75 technology preview
   1448             * @deprecated This API is for technology preview only.
   1449             */
   1450            U_I18N_API const UnicodeString& asText() const;
   1451            /**
   1452             * Non-member swap function.
   1453             * @param p1 will get p2's contents
   1454             * @param p2 will get p1's contents
   1455             *
   1456             * @internal ICU 75 technology preview
   1457             * @deprecated This API is for technology preview only.
   1458             */
   1459            U_I18N_API friend inline void swap(PatternPart& p1, PatternPart& p2) noexcept {
   1460                using std::swap;
   1461 
   1462                swap(p1.piece, p2.piece);
   1463            }
   1464            /**
   1465             * Copy constructor.
   1466             *
   1467             * @internal ICU 75 technology preview
   1468             * @deprecated This API is for technology preview only.
   1469             */
   1470            U_I18N_API PatternPart(const PatternPart& other);
   1471            /**
   1472             * Assignment operator.
   1473             *
   1474             * @internal ICU 75 technology preview
   1475             * @deprecated This API is for technology preview only.
   1476             */
   1477            U_I18N_API PatternPart& operator=(PatternPart) noexcept;
   1478            /**
   1479             * Destructor.
   1480             *
   1481             * @internal ICU 75 technology preview
   1482             * @deprecated This API is for technology preview only.
   1483             */
   1484            U_I18N_API virtual ~PatternPart();
   1485            /**
   1486             * Text part constructor. Returns a text pattern part
   1487             * with text `t`.
   1488             *
   1489             * @param t A text string.
   1490             *
   1491             * @internal ICU 75 technology preview
   1492             * @deprecated This API is for technology preview only.
   1493             */
   1494            U_I18N_API explicit PatternPart(const UnicodeString& t) : piece(t) {}
   1495            /**
   1496             * Expression part constructor. Returns an Expression pattern
   1497             * part with expression `e`.
   1498             *
   1499             * @param e An Expression.
   1500             *
   1501             * @internal ICU 75 technology preview
   1502             * @deprecated This API is for technology preview only.
   1503             */
   1504            U_I18N_API explicit PatternPart(Expression&& e) : piece(e) {}
   1505            /**
   1506             * Markup part constructor. Returns a Markup pattern
   1507             * part with markup `m`
   1508             *
   1509             * @param m A Markup.
   1510             *
   1511             * @internal ICU 75 technology preview
   1512             * @deprecated This API is for technology preview only.
   1513             */
   1514            U_I18N_API explicit PatternPart(Markup&& m) : piece(m) {}
   1515            /**
   1516             * Default constructor.
   1517             * Puts the PatternPart into a valid but undefined state.
   1518             *
   1519             * @internal ICU 75 technology preview
   1520             * @deprecated This API is for technology preview only.
   1521             */
   1522            U_I18N_API PatternPart() = default;
   1523        private:
   1524            friend class Pattern;
   1525 
   1526            std::variant<UnicodeString, Expression, Markup> piece;
   1527        }; // class PatternPart
   1528 
   1529        /**
   1530         *  A `Pattern` is a sequence of formattable parts.
   1531         * It corresponds to the `Pattern` interface
   1532         * defined in https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#patterns
   1533         *
   1534         * `Pattern` is immutable, copyable and movable.
   1535         *
   1536         * @internal ICU 75 technology preview
   1537         * @deprecated This API is for technology preview only.
   1538         */
   1539        class U_I18N_API_CLASS Pattern : public UObject {
   1540        private:
   1541            friend class PatternPart;
   1542 
   1543        public:
   1544            #ifndef U_IN_DOXYGEN
   1545            struct U_I18N_API Iterator;
   1546            #endif
   1547            /**
   1548             * Returns the parts of this pattern
   1549             *
   1550             * @return A forward iterator of variants. Each element is either a string (text part)
   1551             *         or an expression part.
   1552             *
   1553             * @internal ICU 75 technology preview
   1554             * @deprecated This API is for technology preview only.
   1555             */
   1556            U_I18N_API Iterator begin() const {
   1557                return Iterator(this, 0);
   1558            }
   1559            /**
   1560             * Returns a special value to mark the end of iteration
   1561             *
   1562             * @return A forward iterator of variants. This should only be used for comparisons
   1563             *         against an iterator returned by incrementing begin().
   1564             *
   1565             * @internal ICU 75 technology preview
   1566             * @deprecated This API is for technology preview only.
   1567             */
   1568            U_I18N_API Iterator end() const {
   1569                return Iterator(this, len);
   1570            }
   1571            /**
   1572             * The mutable `Pattern::Builder` class allows the pattern to be
   1573             * constructed one part at a time.
   1574             *
   1575             * Builder is not copyable or movable.
   1576             *
   1577             * @internal ICU 75 technology preview
   1578             * @deprecated This API is for technology preview only.
   1579             */
   1580            class U_I18N_API Builder : public UMemory {
   1581            private:
   1582                friend class Pattern;
   1583 
   1584                UVector* parts;  // Not a LocalPointer for the same reason as in `SelectorKeys::Builder`
   1585 
   1586            public:
   1587                /**
   1588                 * Adds a single expression part to the pattern.
   1589                 *
   1590                 * @param part The part to be added (passed by move)
   1591                 * @param status Input/output error code.
   1592                 * @return A reference to the builder.
   1593                 *
   1594                 * @internal ICU 75 technology preview
   1595                 * @deprecated This API is for technology preview only.
   1596                 */
   1597                Builder& add(Expression&& part, UErrorCode& status) noexcept;
   1598                /**
   1599                 * Adds a single markup part to the pattern.
   1600                 *
   1601                 * @param part The part to be added (passed by move)
   1602                 * @param status Input/output error code.
   1603                 * @return A reference to the builder.
   1604                 *
   1605                 * @internal ICU 75 technology preview
   1606                 * @deprecated This API is for technology preview only.
   1607                 */
   1608                Builder& add(Markup&& part, UErrorCode& status) noexcept;
   1609                /**
   1610                 * Adds a single text part to the pattern. Copies `part`.
   1611                 *
   1612                 * @param part The part to be added (passed by move)
   1613                 * @param status Input/output error code.
   1614                 * @return A reference to the builder.
   1615                 *
   1616                 * @internal ICU 75 technology preview
   1617                 * @deprecated This API is for technology preview only.
   1618                 */
   1619                Builder& add(UnicodeString&& part, UErrorCode& status) noexcept;
   1620                /**
   1621                 * Constructs a new immutable `Pattern` using the list of parts
   1622                 * set with previous `add()` calls.
   1623                 *
   1624                 * The builder object (`this`) can still be used after calling `build()`.
   1625                 *
   1626                 * @param status    Input/output error code.
   1627                 * @return          The pattern object
   1628                 *
   1629                 * @internal ICU 75 technology preview
   1630                 * @deprecated This API is for technology preview only.
   1631                 */
   1632                Pattern build(UErrorCode& status) const noexcept;
   1633                /**
   1634                 * Default constructor.
   1635                 * Returns a Builder with an empty sequence of PatternParts.
   1636                 *
   1637                 * @param status Input/output error code
   1638                 *
   1639                 * @internal ICU 75 technology preview
   1640                 * @deprecated This API is for technology preview only.
   1641                 */
   1642                Builder(UErrorCode& status);
   1643                /**
   1644                 * Destructor.
   1645                 *
   1646                 * @internal ICU 75 technology preview
   1647                 * @deprecated This API is for technology preview only.
   1648                 */
   1649                virtual ~Builder();
   1650                Builder(const Builder&) = delete;
   1651                Builder& operator=(const Builder&) = delete;
   1652                Builder(Builder&&) = delete;
   1653                Builder& operator=(Builder&&) = delete;
   1654            }; // class Pattern::Builder
   1655 
   1656            /**
   1657             * Default constructor.
   1658             * Puts the Pattern into a valid but undefined state.
   1659             *
   1660             * @internal ICU 75 technology preview
   1661             * @deprecated This API is for technology preview only.
   1662             */
   1663            U_I18N_API Pattern() : parts(LocalArray<PatternPart>()) {}
   1664            /**
   1665             * Non-member swap function.
   1666             * @param p1 will get p2's contents
   1667             * @param p2 will get p1's contents
   1668             *
   1669             * @internal ICU 75 technology preview
   1670             * @deprecated This API is for technology preview only.
   1671             */
   1672            U_I18N_API friend inline void swap(Pattern& p1, Pattern& p2) noexcept {
   1673                using std::swap;
   1674 
   1675                swap(p1.bogus, p2.bogus);
   1676                swap(p1.len, p2.len);
   1677                swap(p1.parts, p2.parts);
   1678            }
   1679            /**
   1680             * Copy constructor.
   1681             *
   1682             * @internal ICU 75 technology preview
   1683             * @deprecated This API is for technology preview only.
   1684             */
   1685            U_I18N_API Pattern(const Pattern& other);
   1686            /**
   1687             * Assignment operator
   1688             *
   1689             * @internal ICU 75 technology preview
   1690             * @deprecated This API is for technology preview only.
   1691             */
   1692            U_I18N_API Pattern& operator=(Pattern) noexcept;
   1693            /**
   1694             * Destructor.
   1695             *
   1696             * @internal ICU 75 technology preview
   1697             * @deprecated This API is for technology preview only.
   1698             */
   1699            U_I18N_API virtual ~Pattern();
   1700 
   1701            /**
   1702             *  The `Pattern::Iterator` class provides an iterator over the formattable
   1703             * parts of a pattern.
   1704             *
   1705             * `Pattern::Iterator` is mutable and is not copyable or movable.
   1706             *
   1707             * @internal ICU 75 technology preview
   1708             * @deprecated This API is for technology preview only.
   1709             */
   1710            struct U_I18N_API Iterator {
   1711            private:
   1712                using iterator_category = std::forward_iterator_tag;
   1713                using difference_type = std::ptrdiff_t;
   1714                using value_type = std::variant<UnicodeString, Expression, Markup>;
   1715                using pointer = value_type*;
   1716                using reference = const value_type&;
   1717 
   1718                friend class Pattern;
   1719                Iterator(const Pattern* p, int32_t i) : pos(i), pat(p) {}
   1720                friend bool operator== (const Iterator& a, const Iterator& b) { return (a.pat == b.pat && a.pos == b.pos); }
   1721 
   1722                int32_t pos;
   1723                const Pattern* pat;
   1724 
   1725            public:
   1726                /**
   1727                 * Dereference operator (gets the element at the current iterator position)
   1728                 *
   1729                 * @internal ICU 75 technology preview
   1730                 * @deprecated This API is for technology preview only.
   1731                 */
   1732                reference operator*() const {
   1733                    const PatternPart& part = pat->parts[pos];
   1734                    return patternContents(part);
   1735                }
   1736                /**
   1737                 * Increment operator (advances to the next iterator position)
   1738                 *
   1739                 * @internal ICU 75 technology preview
   1740                 * @deprecated This API is for technology preview only.
   1741                 */
   1742                Iterator operator++() { pos++; return *this; }
   1743                /**
   1744                 * Inequality comparison operator (used for comparing an iterator to the result of end())
   1745                 *
   1746                 * @internal ICU 75 technology preview
   1747                 * @deprecated This API is for technology preview only.
   1748                 */
   1749                friend bool operator!= (const Iterator& a, const Iterator& b) { return !(a == b); }
   1750            }; // struct Iterator
   1751 
   1752        private:
   1753            friend class Builder;
   1754            friend class message2::MessageFormatter;
   1755            friend class message2::Serializer;
   1756 
   1757            // Set to true if a copy constructor fails;
   1758            // needed in order to distinguish an uninitialized
   1759            // Pattern from a 0-length pattern
   1760            bool bogus = false;
   1761 
   1762            // Possibly-empty array of parts
   1763            int32_t len = 0;
   1764            LocalArray<PatternPart> parts;
   1765 
   1766            Pattern(const UVector& parts, UErrorCode& status);
   1767            // Helper
   1768            static void initParts(Pattern&, const Pattern&);
   1769 
   1770            /**
   1771             * Returns the size.
   1772             *
   1773             * @return The number of parts in the pattern.
   1774             *
   1775             * @internal ICU 75 technology preview
   1776             * @deprecated This API is for technology preview only.
   1777             */
   1778            int32_t numParts() const;
   1779            /**
   1780             * Returns the `i`th part in the pattern.
   1781             * Precondition: i < numParts()
   1782             *
   1783             * @param i Index of the part being accessed.
   1784             * @return  A reference to the part at index `i`.
   1785             *
   1786             * @internal ICU 75 technology preview
   1787             * @deprecated This API is for technology preview only.
   1788             */
   1789            const PatternPart& getPart(int32_t i) const;
   1790 
   1791            // Gets around not being able to declare Pattern::Iterator as a friend
   1792            // in PatternPart
   1793            static const std::variant<UnicodeString, Expression, Markup>&
   1794                patternContents(const PatternPart& p) { return p.piece; }
   1795        }; // class Pattern
   1796 
   1797        /**
   1798         *  A `Variant` pairs a list of keys with a pattern
   1799         * It corresponds to the `Variant` interface
   1800         * defined in https://github.com/unicode-org/message-format-wg/tree/main/spec/data-model
   1801         *
   1802         * `Variant` is immutable, copyable and movable.
   1803         *
   1804         * @internal ICU 75 technology preview
   1805         * @deprecated This API is for technology preview only.
   1806         */
   1807        class U_I18N_API Variant : public UObject {
   1808        public:
   1809            /**
   1810             * Accesses the pattern of the variant.
   1811             *
   1812             * @return A reference to the pattern.
   1813             *
   1814             * @internal ICU 75 technology preview
   1815             * @deprecated This API is for technology preview only.
   1816             */
   1817            const Pattern& getPattern() const { return p; }
   1818            /**
   1819             * Accesses the keys of the variant.
   1820             *
   1821             * @return A reference to the keys.
   1822             *
   1823             * @internal ICU 75 technology preview
   1824             * @deprecated This API is for technology preview only.
   1825             */
   1826            const SelectorKeys& getKeys() const { return k; }
   1827            /**
   1828             * Constructor. Returns a variant that formats to `pattern`
   1829             * when `keys` match the selector expressions in the enclosing
   1830             * `match` construct.
   1831             *
   1832             * @param keys A reference to a `SelectorKeys`.
   1833             * @param pattern A pattern (passed by move)
   1834             *
   1835             * @internal ICU 75 technology preview
   1836             * @deprecated This API is for technology preview only.
   1837             */
   1838            Variant(const SelectorKeys& keys, Pattern&& pattern) : k(keys), p(std::move(pattern)) {}
   1839            /**
   1840             * Non-member swap function.
   1841             * @param v1 will get v2's contents
   1842             * @param v2 will get v1's contents
   1843             *
   1844             * @internal ICU 75 technology preview
   1845             * @deprecated This API is for technology preview only.
   1846             */
   1847            friend inline void swap(Variant& v1, Variant& v2) noexcept {
   1848                using std::swap;
   1849 
   1850                swap(v1.k, v2.k);
   1851                swap(v1.p, v2.p);
   1852            }
   1853            /**
   1854             * Assignment operator
   1855             *
   1856             * @internal ICU 75 technology preview
   1857             * @deprecated This API is for technology preview only.
   1858             */
   1859            Variant& operator=(Variant other) noexcept;
   1860            /**
   1861             * Default constructor.
   1862             * Returns a Variant in a valid but undefined state.
   1863             *
   1864             * @internal ICU 75 technology preview
   1865             * @deprecated This API is for technology preview only.
   1866             */
   1867            Variant() = default;
   1868            /**
   1869             * Copy constructor.
   1870             *
   1871             * @internal ICU 75 technology preview
   1872             * @deprecated This API is for technology preview only.
   1873             */
   1874            Variant(const Variant&);
   1875            /**
   1876             * Destructor.
   1877             *
   1878             * @internal ICU 75 technology preview
   1879             * @deprecated This API is for technology preview only.
   1880             */
   1881            virtual ~Variant();
   1882        private:
   1883            /* const */ SelectorKeys k;
   1884            /* const */ Pattern p;
   1885        }; // class Variant
   1886 
   1887        /**
   1888         *  A `Binding` pairs a variable name with an expression.
   1889         * It corresponds to the `Declaration` interface
   1890         * defined in https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#messages
   1891         *
   1892         * `Binding` is immutable and copyable. It is not movable.
   1893         *
   1894         * @internal ICU 75 technology preview
   1895         * @deprecated This API is for technology preview only.
   1896         */
   1897        class U_I18N_API Binding : public UObject {
   1898        public:
   1899            /**
   1900             * Accesses the right-hand side of a binding.
   1901             *
   1902             * @return A reference to the expression.
   1903             *
   1904             * @internal ICU 75 technology preview
   1905             * @deprecated This API is for technology preview only.
   1906             */
   1907            const Expression& getValue() const;
   1908            /**
   1909             * Accesses the left-hand side of the binding.
   1910             *
   1911             * @return A reference to the variable name.
   1912             *
   1913             * @internal ICU 75 technology preview
   1914             * @deprecated This API is for technology preview only.
   1915             */
   1916            const VariableName& getVariable() const { return var; }
   1917            /**
   1918             * Constructor for input binding.
   1919             *
   1920             * @param variableName The variable name (left-hand side) of the binding. Passed by move.
   1921             * @param rhs The right-hand side of the input binding. Passed by move.
   1922             *                   `rhs` must have an operand that is a variable reference to `variableName`.
   1923             *                   If `rhs` has an operator, it must be a function call.
   1924             *                   If either of these properties is violated, `errorCode` is set to
   1925             *                   U_INVALID_STATE_ERROR.
   1926             * @param errorCode Input/output error code
   1927             *
   1928             * @internal ICU 75 technology preview
   1929             * @deprecated This API is for technology preview only.
   1930             */
   1931            static Binding input(UnicodeString&& variableName, Expression&& rhs, UErrorCode& errorCode);
   1932            /**
   1933             * Returns true if and only if this binding represents a local declaration.
   1934             * Otherwise, it's an input declaration.
   1935             *
   1936             * @return True if this binding represents a variable and expression;
   1937             *         false if it represents a variable plus an annotation.
   1938             * @internal ICU 78 technology preview
   1939             * @deprecated This API is for technology preview only.
   1940             */
   1941            UBool isLocal() const { return local; }
   1942            /**
   1943             * Constructor.
   1944             *
   1945             * @param v A variable name.
   1946             * @param e An expression.
   1947             *
   1948             * @internal ICU 75 technology preview
   1949             * @deprecated This API is for technology preview only.
   1950             */
   1951            Binding(const VariableName& v, Expression&& e) : var(v), expr(std::move(e)), local(true), annotation(nullptr) {}
   1952            /**
   1953             * Non-member swap function.
   1954             * @param b1 will get b2's contents
   1955             * @param b2 will get b1's contents
   1956             *
   1957             * @internal ICU 75 technology preview
   1958             * @deprecated This API is for technology preview only.
   1959             */
   1960            friend inline void swap(Binding& b1, Binding& b2) noexcept {
   1961                using std::swap;
   1962 
   1963                swap(b1.var, b2.var);
   1964                swap(b1.expr, b2.expr);
   1965                swap(b1.local, b2.local);
   1966                b1.updateAnnotation();
   1967                b2.updateAnnotation();
   1968            }
   1969            /**
   1970             * Copy constructor.
   1971             *
   1972             * @internal ICU 75 technology preview
   1973             * @deprecated This API is for technology preview only.
   1974             */
   1975            Binding(const Binding& other);
   1976            /**
   1977             * Copy assignment operator
   1978             *
   1979             * @internal ICU 75 technology preview
   1980             * @deprecated This API is for technology preview only.
   1981             */
   1982            Binding& operator=(Binding) noexcept;
   1983            /**
   1984             * Default constructor.
   1985             * Puts the Binding into a valid but undefined state.
   1986             *
   1987             * @internal ICU 75 technology preview
   1988             * @deprecated This API is for technology preview only.
   1989             */
   1990            Binding() : local(true) {}
   1991            /**
   1992             * Destructor.
   1993             *
   1994             * @internal ICU 75 technology preview
   1995             * @deprecated This API is for technology preview only.
   1996             */
   1997            virtual ~Binding();
   1998        private:
   1999            friend class message2::Checker;
   2000            friend class message2::MessageFormatter;
   2001            friend class message2::Parser;
   2002            friend class message2::Serializer;
   2003 
   2004            /* const */ VariableName var;
   2005            /* const */ Expression expr;
   2006            /* const */ bool local;
   2007 
   2008            // The following field is always nullptr for a local
   2009            // declaration, and possibly nullptr for an .input declaration
   2010            // If non-null, the referent is a member of `expr` so
   2011            // its lifetime is the same as the lifetime of the enclosing Binding
   2012            // (as long as there's no mutation)
   2013            const Operator* annotation = nullptr;
   2014 
   2015            const OptionMap& getOptionsInternal() const;
   2016 
   2017            bool hasAnnotation() const { return !local && (annotation != nullptr); }
   2018            void updateAnnotation();
   2019        }; // class Binding
   2020 
   2021    // Internal only
   2022 
   2023    #ifndef U_IN_DOXYGEN
   2024    class U_I18N_API_CLASS Matcher : public UObject {
   2025    public:
   2026        U_I18N_API Matcher& operator=(Matcher);
   2027        U_I18N_API Matcher(const Matcher&);
   2028        /**
   2029         * Non-member swap function.
   2030         * @param m1 will get m2's contents
   2031         * @param m2 will get m1's contents
   2032         *
   2033         * @internal ICU 75 technology preview
   2034         * @deprecated This API is for technology preview only.
   2035         */
   2036        U_I18N_API friend inline void swap(Matcher& m1, Matcher& m2) noexcept {
   2037            using std::swap;
   2038 
   2039            if (m1.bogus) {
   2040                m2.bogus = true;
   2041                return;
   2042            }
   2043            if (m2.bogus) {
   2044                m1.bogus = true;
   2045                return;
   2046            }
   2047            swap(m1.selectors, m2.selectors);
   2048            swap(m1.numSelectors, m2.numSelectors);
   2049            swap(m1.variants, m2.variants);
   2050            swap(m1.numVariants, m2.numVariants);
   2051        }
   2052        U_I18N_API virtual ~Matcher();
   2053    private:
   2054 
   2055        friend class MFDataModel;
   2056 
   2057        Matcher(VariableName* ss, int32_t ns, Variant* vs, int32_t nv);
   2058        Matcher() {}
   2059 
   2060        // A Matcher may have numSelectors=0 and numVariants=0
   2061        // (this is a data model error, but it's representable).
   2062        // So we have to keep a separate flag to track failed copies.
   2063        bool bogus = false;
   2064 
   2065        // The variables that are being matched on.
   2066        LocalArray<VariableName> selectors;
   2067        // The number of selectors
   2068        int32_t numSelectors = 0;
   2069        // The list of `when` clauses (case arms).
   2070        LocalArray<Variant> variants;
   2071        // The number of variants
   2072        int32_t numVariants = 0;
   2073    }; // class Matcher
   2074    #endif
   2075 
   2076    // -----------------------------------------------------------------------
   2077    // Public MFDataModel class
   2078 
   2079    /**
   2080     *
   2081     * The `MFDataModel` class describes a parsed representation of the text of a message.
   2082     * This representation is public as higher-level APIs for messages will need to know its public
   2083     * interface: for example, to re-instantiate a parsed message with different values for imported
   2084     variables.
   2085     *
   2086     * The MFDataModel API implements <a target="github"
   2087     href="https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md">the
   2088     * specification of the abstract syntax (data model representation)</a> for MessageFormat.
   2089     *
   2090     * `MFDataModel` is immutable, copyable and movable.
   2091     *
   2092     * @internal ICU 75 technology preview
   2093     * @deprecated This API is for technology preview only.
   2094     */
   2095    class U_I18N_API_CLASS MFDataModel : public UMemory {
   2096        /*
   2097          Classes that represent nodes in the data model are nested inside the
   2098          `MFDataModel` class.
   2099 
   2100          Classes such as `Expression`, `Pattern` and `VariantMap` are immutable and
   2101          are constructed using the builder pattern.
   2102 
   2103          Most classes representing nodes have copy constructors. This is because builders
   2104          contain immutable data that must be copied when calling `build()`, since the builder
   2105          could go out of scope before the immutable result of the builder does. Copying is
   2106          also necessary to prevent unexpected mutation if intermediate builders are saved
   2107          and mutated again after calling `build()`.
   2108 
   2109          The copy constructors perform a deep copy, for example by copying the entire
   2110          list of options for an `Operator` (and copying the entire underlying vector.)
   2111          Some internal fields should be `const`, but are declared as non-`const` to make
   2112          the copy constructor simpler to implement. (These are noted throughout.) In
   2113          other words, those fields are `const` except during the execution of a copy
   2114          constructor.
   2115 
   2116          On the other hand, intermediate `Builder` methods that return a `Builder&`
   2117          mutate the state of the builder, so in code like:
   2118 
   2119          Expression::Builder& exprBuilder = Expression::builder()-> setOperand(foo);
   2120          Expression::Builder& exprBuilder2 = exprBuilder.setOperator(bar);
   2121 
   2122          the call to `setOperator()` would mutate `exprBuilder`, since `exprBuilder`
   2123          and `exprBuilder2` are references to the same object.
   2124 
   2125          An alternate choice would be to make `build()` destructive, so that copying would
   2126          be unnecessary. Or, both copying and moving variants of `build()` could be
   2127          provided. Copying variants of the intermediate `Builder` methods could be
   2128          provided as well, if this proved useful.
   2129        */
   2130    public:
   2131        /**
   2132         * Accesses the local variable declarations for this data model.
   2133         *
   2134         * @return A vector of bindings for local variables.
   2135         *
   2136         * @internal ICU 75 technology preview
   2137         * @deprecated This API is for technology preview only.
   2138         */
   2139        U_I18N_API std::vector<Binding> getLocalVariables() const {
   2140            std::vector<Binding> result;
   2141            if (!bogus) {
   2142                return toStdVector<Binding>(bindings.getAlias(), bindingsLen);
   2143            }
   2144            return {};
   2145        }
   2146        /**
   2147         * Accesses the selectors. Returns an empty vector if this is a pattern message.
   2148         *
   2149         * @return A vector of selectors.
   2150         *
   2151         * @internal ICU 75 technology preview
   2152         * @deprecated This API is for technology preview only.
   2153         */
   2154        U_I18N_API std::vector<VariableName> getSelectors() const {
   2155            if (std::holds_alternative<Pattern>(body)) {
   2156                return {};
   2157            }
   2158            const Matcher* match = std::get_if<Matcher>(&body);
   2159            // match must be non-null, given the previous check
   2160            return toStdVector<VariableName>(match->selectors.getAlias(), match->numSelectors);
   2161        }
   2162        /**
   2163         * Accesses the variants. Returns an empty vector if this is a pattern message.
   2164         *
   2165         * @return A vector of variants.
   2166         *
   2167         * @internal ICU 75 technology preview
   2168         * @deprecated This API is for technology preview only.
   2169         */
   2170        U_I18N_API std::vector<Variant> getVariants() const {
   2171            // Return empty vector if no variants
   2172            if (std::holds_alternative<Pattern>(body)) {
   2173                return {};
   2174            }
   2175            const Matcher* match = std::get_if<Matcher>(&body);
   2176            // match must be non-null, given the previous check
   2177            return toStdVector<Variant>(match->variants.getAlias(), match->numVariants);
   2178            return {};
   2179        }
   2180        /**
   2181         * Accesses the pattern (in a message without selectors).
   2182         * Returns a reference to an empty pattern if the message has selectors.
   2183         *
   2184         * @return A reference to the pattern.
   2185         *
   2186         * @internal ICU 75 technology preview
   2187         * @deprecated This API is for technology preview only.
   2188         */
   2189        U_I18N_API const Pattern& getPattern() const;
   2190        /**
   2191         * The mutable `MFDataModel::Builder` class allows the data model to be
   2192         * constructed incrementally.
   2193         *
   2194         * @internal ICU 75 technology preview
   2195         * @deprecated This API is for technology preview only.
   2196         */
   2197        class U_I18N_API Builder;
   2198        /**
   2199         * Default constructor.
   2200         * Puts the MFDataModel into a valid but undefined state.
   2201         *
   2202         * @internal ICU 75 technology preview
   2203         * @deprecated This API is for technology preview only.
   2204         */
   2205        U_I18N_API MFDataModel();
   2206        /**
   2207         * Non-member swap function.
   2208         * @param m1 will get m2's contents
   2209         * @param m2 will get m1's contents
   2210         *
   2211         * @internal ICU 75 technology preview
   2212         * @deprecated This API is for technology preview only.
   2213         */
   2214        U_I18N_API friend inline void swap(MFDataModel& m1, MFDataModel& m2) noexcept {
   2215            using std::swap;
   2216 
   2217            if (m1.bogus) {
   2218                m2.bogus = true;
   2219                return;
   2220            }
   2221            if (m2.bogus) {
   2222                m1.bogus = true;
   2223                return;
   2224            }
   2225            swap(m1.body, m2.body);
   2226            swap(m1.bindings, m2.bindings);
   2227            swap(m1.bindingsLen, m2.bindingsLen);
   2228        }
   2229        /**
   2230         * Assignment operator
   2231         *
   2232         * @internal ICU 75 technology preview
   2233         * @deprecated This API is for technology preview only.
   2234         */
   2235        U_I18N_API MFDataModel& operator=(MFDataModel) noexcept;
   2236        /**
   2237         * Copy constructor.
   2238         *
   2239         * @internal ICU 75 technology preview
   2240         * @deprecated This API is for technology preview only.
   2241         */
   2242        U_I18N_API MFDataModel(const MFDataModel& other);
   2243        /**
   2244         * Destructor.
   2245         *
   2246         * @internal ICU 75 technology preview
   2247         * @deprecated This API is for technology preview only.
   2248         */
   2249        U_I18N_API virtual ~MFDataModel();
   2250 
   2251        /**
   2252         * The mutable `MFDataModel::Builder` class allows the data model to be
   2253         * constructed incrementally. Builder is not copyable or movable.
   2254         *
   2255         * @internal ICU 75 technology preview
   2256         * @deprecated This API is for technology preview only.
   2257         */
   2258        class U_I18N_API Builder : public UMemory {
   2259        private:
   2260            friend class MFDataModel;
   2261 
   2262            void checkDuplicate(const VariableName&, UErrorCode&) const;
   2263            void buildSelectorsMessage(UErrorCode&);
   2264            bool hasPattern = true;
   2265            bool hasSelectors = false;
   2266            Pattern pattern;
   2267            // The following members are not LocalPointers for the same reason as in SelectorKeys::Builder
   2268            UVector* selectors = nullptr;
   2269            UVector* variants = nullptr;
   2270            UVector* bindings = nullptr;
   2271        public:
   2272            /**
   2273             * Adds a binding, There must not already be a binding
   2274             * with the same name.
   2275             *
   2276             * @param b The binding. Passed by move.
   2277             * @param status Input/output error code. Set to U_DUPLICATE_DECLARATION_ERROR
   2278             *                   if `addBinding()` was previously called with a binding
   2279             *                   with the same variable name as `b`.
   2280             *
   2281             * @internal ICU 75 technology preview
   2282             * @deprecated This API is for technology preview only.
   2283             */
   2284            Builder& addBinding(Binding&& b, UErrorCode& status);
   2285            /**
   2286             * Adds a selector variable.
   2287             * If a pattern was previously set, clears the pattern.
   2288             *
   2289             * @param selector Variable to add as a selector. Passed by move.
   2290             * @param errorCode Input/output error code
   2291             * @return A reference to the builder.
   2292             *
   2293             * @internal ICU 75 technology preview
   2294             * @deprecated This API is for technology preview only.
   2295             */
   2296            Builder& addSelector(VariableName&& selector, UErrorCode& errorCode);
   2297            /**
   2298             * Adds a single variant.
   2299             * If a pattern was previously set using `setPattern()`, clears the pattern.
   2300             *
   2301             * @param keys Keys for the variant. Passed by move.
   2302             * @param pattern Pattern for the variant. Passed by move.
   2303             * @param errorCode Input/output error code
   2304             * @return A reference to the builder.
   2305             *
   2306             * @internal ICU 75 technology preview
   2307             * @deprecated This API is for technology preview only.
   2308             */
   2309            Builder& addVariant(SelectorKeys&& keys, Pattern&& pattern, UErrorCode& errorCode) noexcept;
   2310            /**
   2311             * Sets the body of the message as a pattern.
   2312             * If selectors and/or variants were previously set, clears them.
   2313             *
   2314             * @param pattern Pattern to represent the body of the message.
   2315             *                Passed by move.
   2316             * @return A reference to the builder.
   2317             *
   2318             * @internal ICU 75 technology preview
   2319             * @deprecated This API is for technology preview only.
   2320             */
   2321            Builder& setPattern(Pattern&& pattern);
   2322            /**
   2323             * Constructs a new immutable data model.
   2324             * If `setPattern()` has not been called and if `addSelector()` and
   2325             * `addVariant()` were not each called at least once,
   2326             * `status` is set to `U_INVALID_STATE_ERROR`.
   2327             * If `addSelector()` was called and `addVariant()` was never called,
   2328             * or vice versa, then `status` is set to U_INVALID_STATE_ERROR.
   2329             * Otherwise, either a Pattern or Selectors message is constructed
   2330             * based on the pattern that was previously set, or selectors and variants
   2331             * that were previously set.
   2332             *
   2333             * The builder object (`this`) can still be used after calling `build()`.
   2334             *
   2335             * @param status Input/output error code.
   2336             * @return       The new MFDataModel
   2337             *
   2338             * @internal ICU 75 technology preview
   2339             * @deprecated This API is for technology preview only.
   2340             */
   2341            MFDataModel build(UErrorCode& status) const noexcept;
   2342            /**
   2343             * Default constructor.
   2344             * Returns a Builder with no pattern or selectors set.
   2345             * Either `setPattern()` or both `addSelector()` and
   2346             * `addVariant()` must be called before calling `build()`
   2347             * on the resulting builder.
   2348             *
   2349             * @param status Input/output error code.
   2350             *
   2351             * @internal ICU 75 technology preview
   2352             * @deprecated This API is for technology preview only.
   2353             */
   2354            Builder(UErrorCode& status);
   2355            /**
   2356             * Destructor.
   2357             *
   2358             * @internal ICU 75 technology preview
   2359             * @deprecated This API is for technology preview only.
   2360             */
   2361            virtual ~Builder();
   2362            Builder(const Builder&) = delete;
   2363            Builder& operator=(const Builder&) = delete;
   2364            Builder(Builder&&) = delete;
   2365            Builder& operator=(Builder&&) = delete;
   2366        }; // class Builder
   2367 
   2368    private:
   2369        friend class message2::Checker;
   2370        friend class message2::MessageFormatter;
   2371        friend class message2::Serializer;
   2372 
   2373        Pattern empty; // Provided so that `getPattern()` can return a result
   2374                       // if called on a selectors message
   2375        bool hasPattern() const { return std::holds_alternative<Pattern>(body); }
   2376 
   2377        bool bogus = false; // Set if a copy constructor fails
   2378 
   2379        // A message body is either a matcher (selector list and variant list),
   2380        // or a single pattern
   2381        std::variant<Matcher, Pattern> body;
   2382 
   2383        // Bindings for local variables
   2384        /* const */ LocalArray<Binding> bindings;
   2385        int32_t bindingsLen = 0;
   2386 
   2387        const Binding* getLocalVariablesInternal() const;
   2388        const VariableName* getSelectorsInternal() const;
   2389        const Variant* getVariantsInternal() const;
   2390 
   2391        int32_t numSelectors() const {
   2392            const Matcher* matcher = std::get_if<Matcher>(&body);
   2393            return (matcher == nullptr ? 0 : matcher->numSelectors);
   2394        }
   2395        int32_t numVariants() const {
   2396            const Matcher* matcher = std::get_if<Matcher>(&body);
   2397            return (matcher == nullptr ? 0 : matcher->numVariants);
   2398        }
   2399 
   2400        // Helper
   2401        void initBindings(const Binding*);
   2402 
   2403        MFDataModel(const Builder& builder, UErrorCode&) noexcept;
   2404    }; // class MFDataModel
   2405  } // namespace data_model
   2406 } // namespace message2
   2407 
   2408 U_NAMESPACE_END
   2409 
   2410 #endif // U_HIDE_DEPRECATED_API
   2411 
   2412 #endif /* #if !UCONFIG_NO_MF2 */
   2413 
   2414 #endif /* #if !UCONFIG_NO_FORMATTING */
   2415 
   2416 #endif /* #if !UCONFIG_NO_NORMALIZATION */
   2417 
   2418 #endif /* U_SHOW_CPLUSPLUS_API */
   2419 
   2420 #endif // MESSAGEFORMAT_DATA_MODEL_H
   2421 
   2422 // eof