#ifndef XRPL_PROTOCOL_SOTEMPLATE_H_INCLUDED #define XRPL_PROTOCOL_SOTEMPLATE_H_INCLUDED #include #include #include #include #include namespace ripple { /** Kind of element in each entry of an SOTemplate. */ enum SOEStyle { soeINVALID = -1, soeREQUIRED = 0, // required soeOPTIONAL = 1, // optional, may be present with default value soeDEFAULT = 2, // optional, if present, must not have default value // inner object with the default fields has to be // constructed with STObject::makeInnerObject() }; /** Amount fields that can support MPT */ enum SOETxMPTIssue { soeMPTNone, soeMPTSupported, soeMPTNotSupported }; //------------------------------------------------------------------------------ /** An element in a SOTemplate. */ class SOElement { // Use std::reference_wrapper so SOElement can be stored in a std::vector. std::reference_wrapper sField_; SOEStyle style_; SOETxMPTIssue supportMpt_ = soeMPTNone; private: void init(SField const& fieldName) const { if (!sField_.get().isUseful()) { auto nm = std::to_string(fieldName.getCode()); if (fieldName.hasName()) nm += ": '" + fieldName.getName() + "'"; Throw( "SField (" + nm + ") in SOElement must be useful."); } } public: SOElement(SField const& fieldName, SOEStyle style) : sField_(fieldName), style_(style) { init(fieldName); } template requires(std::is_same_v || std::is_same_v) SOElement( TypedField const& fieldName, SOEStyle style, SOETxMPTIssue supportMpt = soeMPTNotSupported) : sField_(fieldName), style_(style), supportMpt_(supportMpt) { init(fieldName); } SField const& sField() const { return sField_.get(); } SOEStyle style() const { return style_; } SOETxMPTIssue supportMPT() const { return supportMpt_; } }; //------------------------------------------------------------------------------ /** Defines the fields and their attributes within a STObject. Each subclass of SerializedObject will provide its own template describing the available fields and their metadata attributes. */ class SOTemplate { public: // Copying vectors is expensive. Make this a move-only type until // there is motivation to change that. SOTemplate(SOTemplate&& other) = default; SOTemplate& operator=(SOTemplate&& other) = default; /** Create a template populated with all fields. After creating the template fields cannot be added, modified, or removed. */ SOTemplate( std::initializer_list uniqueFields, std::initializer_list commonFields = {}); /* Provide for the enumeration of fields */ std::vector::const_iterator begin() const { return elements_.cbegin(); } std::vector::const_iterator cbegin() const { return begin(); } std::vector::const_iterator end() const { return elements_.cend(); } std::vector::const_iterator cend() const { return end(); } /** The number of entries in this template */ std::size_t size() const { return elements_.size(); } /** Retrieve the position of a named field. */ int getIndex(SField const&) const; SOEStyle style(SField const& sf) const { return elements_[indices_[sf.getNum()]].style(); } private: std::vector elements_; std::vector indices_; // field num -> index }; } // namespace ripple #endif