2 /******************************************************************************
4 * Copyright (c) 2019 AT&T Intellectual Property.
5 * Copyright (c) 2018-2019 Nokia.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 ******************************************************************************/
21 // Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries
23 // Local Includes: Application specific classes, functions, and libraries
24 #include "asn/elements.hpp"
25 #include "asn/ber/common.hpp"
26 #include "asn/ber/context.hpp"
27 #include "asn/ber/tag.hpp"
28 #include "asn/ber/length.hpp"
29 #include "asn/ber/visitor.hpp"
30 #include "asn/ber/opentype.hpp"
35 /********************************************************************************
37 *********************************************************************************/
39 bool pack(IE const& ie, EncoderCtx& ctx)
41 ctx.refErrorCtx().reset();
42 Element<IE>::run(ie, ctx);
45 Tools::bit_accessor::padByte(ctx.refBuffer());
47 return static_cast<bool>(ctx);
49 /********************************************************************************
51 *********************************************************************************/
53 bool unpack(IE& ie, DecoderCtx& ctx)
55 Element<IE>::run(ie, ctx);
58 Tools::bit_accessor::padByte(ctx.refBuffer());
60 if(ctx && ctx.refBuffer().getBytesLeft())
62 ctx.ie_name(IE::name());
63 ctx.refErrorCtx().lengthErrorBytes(ctx.refBuffer().getBytesLeft(), 0);
66 return static_cast<bool>(ctx);
69 /***************************************************************************************
71 ***************************************************************************************/
72 template <class IE, class Enabler = void>
75 /***************************************************************************************
76 * ExplicitCodec: Codec for elements with EXPLICIT tag
77 ***************************************************************************************/
81 using tag_t = Tag<IE, true>;
82 static bool inline is_matched(tag_value_t _tag) {return _tag == tag_t::value();}
84 static void inline run(IE const& ie, EncoderCtx& ctx)
86 auto & buffer = ctx.refBuffer();
89 u8* len_ptr = buffer.advance(1); //reserve for the length
91 Element<typename IE::parent_t>::run(static_cast<typename IE::parent_t const&>(ie), ctx);
93 size_t len = buffer.begin() - len_ptr - 1;
96 len_ptr[0] = 0x80; //undefinite length form per X.690 8.1.3.6
97 uint8_t buff[2] = {0}; // end-of-contents octets (X.690 8.1.5)
98 buffer.putBytes(buff, sizeof(buff));
102 len_ptr[0] = static_cast<u8>(len); //one byte form per X.690 8.1.3.4
106 static void inline run(IE& ie, DecoderCtx& ctx, tag_value_t tag)
108 if(tag_t::value() != tag)
109 ctx.refErrorCtx().tagError(static_cast<uint32_t>(tag));
112 auto & buffer = ctx.refBuffer();
113 size_t length = Length::decode(ctx);
115 ASN_DECODER_TRACE("EX<tag=0x%x length=%zu> buffer: %s", static_cast<int>(tag), length, ctx.refBuffer().toString());
117 if(length == indefinite_length)
119 Element<typename IE::parent_t>::run(static_cast<typename IE::parent_t&>(ie), ctx);
123 uint8_t const* data_in = ctx.refBuffer().getBytes(2);
124 if(data_in && (data_in[0] || data_in[1]))
126 ctx.refErrorCtx().errorWrongEndOfContent();
132 if (buffer.getBytesLeft() < length)
134 ctx.refErrorCtx().lengthErrorBytes(buffer.getBytesLeft(), length);
138 DecoderCtx::buf_type::pointer end = buffer.end();
139 buffer.set_end(buffer.begin() + length);
141 Element<typename IE::parent_t>::run(static_cast<typename IE::parent_t&>(ie), ctx);
151 /***************************************************************************************
152 * BOOLEAN: Encoding the boolean type (X.690 8.2)
153 ***************************************************************************************/
155 struct ElementType<IE, std::enable_if_t<IE::ie_type == element_type::T_BOOLEAN> >
157 using tag_t = Tag<IE, false>;
159 static bool inline is_matched(tag_value_t tag) {return tag == tag_t::value();}
161 static void inline run(IE const& ie, EncoderCtx& ctx)
164 Length::encode(1, ctx);
166 Tools::put_bytes(0xFF, 1, ctx);
168 Tools::put_bytes(0, 1, ctx);
171 static void inline run(IE& ie, DecoderCtx& ctx, tag_value_t tag)
173 if(tag_t::value() != tag)
174 ctx.refErrorCtx().tagError(static_cast<uint32_t>(tag));
177 size_t length = Length::decode(ctx);
180 ctx.refErrorCtx().sizeRangeError(length, 1, 1);
184 ASN_DECODER_TRACE("IE<type=%d name=%s tag=0x%x length=%zu> buffer: %s", static_cast<int>(IE::ie_type), IE::name(), static_cast<int>(tag), length, ctx.refBuffer().toString());
186 Tools::get_bytes(value, 1, ctx);
192 /***************************************************************************************
193 * INTEGER: Encoding the integer type (X.690 8.3)
194 ***************************************************************************************/
196 struct ElementType<IE, std::enable_if_t<IE::ie_type == element_type::T_INTEGER> >
198 using tag_t = Tag<IE, false>;
200 static bool inline is_matched(tag_value_t tag) {return tag == tag_t::value();}
202 static void inline run(IE const& ie, EncoderCtx& ctx)
205 size_t length = Length::get(ie.get());
206 Length::encode(length, ctx);
207 Tools::put_bytes(ie.get(), length, ctx);
209 static void inline run(IE& ie, DecoderCtx& ctx, tag_value_t tag)
211 if(tag_t::value() != tag)
213 ctx.refErrorCtx().tagError(static_cast<uint32_t>(tag));
217 size_t length = Length::decode(ctx);
218 if(!length || length == indefinite_length)
219 ctx.refErrorCtx().sizeRangeError(length);
222 ASN_DECODER_TRACE("IE<type=%d name=%s tag=0x%x length=%zu> buffer: %s", static_cast<int>(IE::ie_type), IE::name(), static_cast<int>(tag), length, ctx.refBuffer().toString());
223 typename IE::value_type value;
224 Tools::get_bytes(value, length, ctx);
230 /***************************************************************************************
231 * ENUMERATED: Encoding the enumerated type (X.690 8.4)
232 ***************************************************************************************/
234 struct ElementType<IE, std::enable_if_t<IE::ie_type == element_type::T_ENUMERATED> >
236 using tag_t = Tag<IE, false>;
238 static bool inline is_matched(tag_value_t tag) {return tag == tag_t::value();}
240 static void inline run(IE const& ie, EncoderCtx& ctx)
243 size_t length = Length::get(ie.get());
244 Length::encode(length, ctx);
245 Tools::put_bytes(ie.get(), length, ctx);
247 static void inline run(IE& ie, DecoderCtx& ctx, tag_value_t tag)
249 if(tag_t::value() != tag)
250 ctx.refErrorCtx().tagError(static_cast<uint32_t>(tag));
253 size_t length = Length::decode(ctx);
254 if(!length || length == indefinite_length)
255 ctx.refErrorCtx().sizeRangeError(length);
258 ASN_DECODER_TRACE("IE<type=%d name=%s tag=0x%x length=%zu> buffer: %s", static_cast<int>(IE::ie_type), IE::name(), static_cast<int>(tag), length, ctx.refBuffer().toString());
259 typename IE::value_type value;
260 Tools::get_bytes(value, length, ctx);
266 /***************************************************************************************
267 * REAL: Encoding the real type (X.690 8.5)
268 ***************************************************************************************/
270 /***************************************************************************************
271 * BIT STRING: Encoding the bitstring type (X.690 8.6)
272 ***************************************************************************************/
274 struct ElementType<IE, std::enable_if_t<(IE::ie_type == element_type::T_BITSTRING)> >
276 using tag_t = Tag<IE, false>;
277 using ctag_t = Tag<IE, true>;
279 static bool inline is_matched(tag_value_t tag) {return tag == tag_t::value() || tag == ctag_t::value();}
281 static void inline run(IE const& ie, EncoderCtx& ctx)
285 uint8_t tail = ie.get_bitqty() % 8;
287 size_t length = ie.get_buffer().size();
288 Length::encode(length + 1, ctx);
290 auto & buffer = ctx.refBuffer();
291 buffer.putByte((8 - tail) & 0x7F);
295 buffer.putBytes(ie.get_buffer().data(), length - 1);
296 u8 last_byte = *(ie.get_buffer().data() + length - 1);
298 last_byte <<= 8 - tail;
299 buffer.putBytes(&last_byte, 1);
303 buffer.putBytes(ie.get_buffer().data(), length);
306 static void inline run(IE& ie, DecoderCtx& ctx, tag_value_t tag)
309 if(tag_t::value() == tag)
311 size_t length = Length::decode(ctx);
312 if(!length || length == indefinite_length)
314 ctx.refErrorCtx().sizeRangeError(length);
318 ASN_DECODER_TRACE("IE<type=%d name=%s tag=0x%x length=%zu> buffer: %s", static_cast<int>(IE::ie_type), IE::name(), static_cast<int>(tag), length, ctx.refBuffer().toString());
319 uint8_t const* data_in = ctx.refBuffer().getBytes(length);
322 size_t len_bytes = length - 1;
323 size_t bitqty = len_bytes << 3;
325 if((data_in[0] & 0x80) || (bitqty < data_in[0]))
327 ctx.refErrorCtx().valueRangeError(data_in[0]);
331 bitqty = bitqty - data_in[0];
332 uint8_t* data_out = ctx.refAllocator().alloc_bytes(len_bytes);
335 memcpy(data_out, &data_in[1], len_bytes);
336 const u8 shift = bitqty % 8;
339 data_out[len_bytes - 1] >>= 8 - shift;
341 ie.set_buffer(bitqty, data_out);
345 ctx.refErrorCtx().allocatorNoMem(0, len_bytes);
351 else if(ctag_t::value() == tag)
353 //todo: implement the segmented data
354 ctx.refErrorCtx().errorUnsupported();
358 ctx.refErrorCtx().tagError(static_cast<uint32_t>(tag));
362 /***************************************************************************************
363 * OCTET STRING: Encoding the octetstring type (X.690 8.7)
364 * Restricted Character string types (X.690 8.23)
365 ***************************************************************************************/
367 struct ElementType<IE, std::enable_if_t<IE::ie_type == element_type::T_OCTETSTRING> >
369 using tag_t = Tag<IE, false>;
370 using ctag_t = Tag<IE, true>;
372 static bool inline is_matched(tag_value_t tag) {return tag == tag_t::value() || tag == ctag_t::value();}
374 static void inline run(IE const& ie, EncoderCtx& ctx)
377 size_t length = ie.get().size();
378 Length::encode(length, ctx);
379 ctx.refBuffer().putBytes(ie.get().data(), length);
381 static void inline run(IE& ie, DecoderCtx& ctx, tag_value_t tag)
384 if(tag_t::value() == tag)
386 size_t length = Length::decode(ctx);
387 if(length == indefinite_length)
389 ctx.refErrorCtx().sizeRangeError(length);
393 ASN_DECODER_TRACE("IE<type=%d name=%s tag=0x%x length=%zu> buffer: %s", static_cast<int>(IE::ie_type), IE::name(), static_cast<int>(tag), length, ctx.refBuffer().toString());
394 uint8_t const* data_in = ctx.refBuffer().getBytes(length);
397 ie.set(length, data_in);
401 else if(ctag_t::value() == tag)
403 //todo: implement the segmented data
404 ctx.refErrorCtx().errorUnsupported();
408 ctx.refErrorCtx().tagError(static_cast<uint32_t>(tag));
412 /***************************************************************************************
413 * NULL: Encoding the null type (X.690 8.8)
414 ***************************************************************************************/
416 struct ElementType<IE, std::enable_if_t<IE::ie_type == element_type::T_NULL> >
418 using tag_t = Tag<IE, false>;
420 static bool inline is_matched(tag_value_t tag) {return tag == tag_t::value();}
422 static void inline run(IE const& ie, EncoderCtx& ctx)
425 Length::encode(0, ctx);
428 static void inline run(IE& ie, DecoderCtx& ctx, tag_value_t tag)
430 if(tag_t::value() != tag)
431 ctx.refErrorCtx().tagError(static_cast<uint32_t>(tag));
434 size_t length = Length::decode(ctx);
436 ctx.refErrorCtx().sizeRangeError(length);
437 ASN_DECODER_TRACE("IE<type=%d name=%s tag=0x%x length=%zu> buffer: %s", static_cast<int>(IE::ie_type), IE::name(), static_cast<int>(tag), length, ctx.refBuffer().toString());
441 /***************************************************************************************
442 * SEQUENCE: Encoding the sequence type (X.690 8.9)
443 * SET: Encoding the set type (X.690 8.11)
444 ***************************************************************************************/
446 struct ElementType<IE, std::enable_if_t<(IE::ie_type == element_type::T_SEQUENCE) || (IE::ie_type == element_type::T_SET)> >
448 using tag_t = Tag<IE, true>;
450 static bool inline is_matched(tag_value_t tag) {return tag == tag_t::value();}
452 static void inline run(IE const& ie, EncoderCtx& ctx)
454 auto & buffer = ctx.refBuffer();
457 u8* len_ptr = buffer.advance(1); //reserve for the length
459 VisitorEncoderSeq<IE> ve(ctx, ie);
462 size_t len = buffer.begin() - len_ptr - 1;
465 len_ptr[0] = 0x80; //undefinite length form per X.690 8.1.3.6
466 uint8_t buff[2] = {0}; // end-of-contents octets (X.690 8.1.5)
467 buffer.putBytes(buff, sizeof(buff));
470 len_ptr[0] = static_cast<u8>(len); //one byte form per X.690 8.1.3.4
473 static void inline run(IE& ie, DecoderCtx& ctx, tag_value_t tag) //todo: support arbitrary order of IEs in SET
475 if(tag_t::value() != tag)
476 ctx.refErrorCtx().tagError(static_cast<uint32_t>(tag));
479 VisitorDecoderSeq<IE> vd(ctx, ie);
480 auto & buffer = ctx.refBuffer();
482 size_t length = Length::decode(ctx);
484 ASN_DECODER_TRACE("IE<type=%d name=%s tag=0x%x length=%zu> buffer: %s", static_cast<int>(IE::ie_type), IE::name(), static_cast<int>(tag), length, ctx.refBuffer().toString());
486 if(length == indefinite_length)
491 if(invalid_tag != vd.get_unhandled_tag())
493 tag_value_t _tag = vd.get_unhandled_tag();
494 if(IE::constraint_t::extended) //skip the unknown extension now
496 tag_value_t const* tag_ptr = &_tag;
500 _tag = OpenType::decode(ctx, _length, tag_ptr);
503 } while(ctx && !(_tag == 0 && _length == 0));
505 else // it should be the end-of-contents octets (8.1.5)
507 uint8_t const* data_in = ctx.refBuffer().getBytes(1);
508 if(data_in && (_tag || data_in[0]))
510 ctx.refErrorCtx().errorWrongEndOfContent();
516 uint8_t const* data_in = ctx.refBuffer().getBytes(2);
517 if(data_in && (data_in[0] || data_in[1]))
519 ctx.refErrorCtx().errorWrongEndOfContent();
526 if (buffer.getBytesLeft() < length)
528 ctx.refErrorCtx().lengthErrorBytes(buffer.getBytesLeft(), length);
532 DecoderCtx::buf_type::pointer end = buffer.end();
533 buffer.set_end(buffer.begin() + length);
535 tag_value_t _tag = vd.get_unhandled_tag();
536 if(invalid_tag != _tag)
538 if(IE::constraint_t::extended) //skip the unknown extension now
540 tag_value_t const* tag_ptr = &_tag;
544 _tag = OpenType::decode(ctx, _length, tag_ptr);
547 } while(ctx && buffer.getBytesLeft() > 0);
550 ctx.refErrorCtx().tagError(static_cast<uint32_t>(tag)); // unexpected tag
559 /***************************************************************************************
560 * SEQUENCE OF: Encoding the sequence-of type (X.690 8.10)
561 * SET OF: Encoding the set-of type (X.690 8.12)
562 ***************************************************************************************/
564 struct ElementType<IE, std::enable_if_t<(IE::ie_type == element_type::T_SEQUENCE_OF) || (IE::ie_type == element_type::T_SET_OF)> >
566 using tag_t = Tag<IE, true>;
568 static bool inline is_matched(tag_value_t tag) {return tag == tag_t::value();}
570 static void inline run(IE const& ie, EncoderCtx& ctx)
572 auto & buffer = ctx.refBuffer();
575 u8* len_ptr = buffer.advance(1); //reserve for the length
577 for (auto& elem : ie)
579 Element<typename IE::element_t>::run(elem, ctx);
582 size_t len = buffer.begin() - len_ptr - 1;
585 len_ptr[0] = 0x80; //undefinite length form per X.690 8.1.3.6
586 uint8_t buff[2] = {0}; // end-of-contents octets (X.690 8.1.5)
587 buffer.putBytes(buff, sizeof(buff));
590 len_ptr[0] = static_cast<u8>(len); //one byte form per X.690 8.1.3.4
592 static void inline run(IE& ie, DecoderCtx& ctx, tag_value_t tag)
596 if(tag_t::value() != tag)
597 ctx.refErrorCtx().tagError(static_cast<uint32_t>(tag));
600 auto & buffer = ctx.refBuffer();
602 size_t length = Length::decode(ctx);
604 ASN_DECODER_TRACE("IE<type=%d name=%s tag=0x%x length=%zu> buffer: %s", static_cast<int>(IE::ie_type), IE::name(), static_cast<int>(tag), length, ctx.refBuffer().toString());
606 if(length == indefinite_length)
608 tag_value_t elm_tag = get_tag(ctx);
610 while(ctx && Element<typename IE::element_t>::is_matched(elm_tag))
612 add_element(ie, ctx, &elm_tag);
613 elm_tag = get_tag(ctx);
618 uint8_t const* data_in = ctx.refBuffer().getBytes(1);
619 if(data_in && (elm_tag || data_in[0]))
621 ctx.refErrorCtx().errorWrongEndOfContent();
627 if (buffer.getBytesLeft() < length)
629 ctx.refErrorCtx().lengthErrorBytes(buffer.getBytesLeft(), length);
633 DecoderCtx::buf_type::pointer end = buffer.end();
634 buffer.set_end(buffer.begin() + length);
636 while(ctx && buffer.getBytesLeft() > 0)
637 add_element(ie, ctx);
646 static void inline add_element(IE& ie, DecoderCtx& ctx, tag_value_t const* elm_tag = nullptr)
648 uint8_t* data = ctx.refAllocator().alloc_bytes(sizeof(typename IE::value_type));
651 typename IE::value_type * v = new (data) typename IE::value_type;
654 Element<typename IE::element_t>::run(*v, ctx, elm_tag);
658 ctx.refErrorCtx().allocatorNoMem(0, sizeof(typename IE::value_type));
663 /***************************************************************************************
664 * CHOICE: Encoding the choice type
665 ***************************************************************************************/
666 struct ChoiceVisitorEncoder
668 ChoiceVisitorEncoder(EncoderCtx& ctx) : m_ctx(ctx) {}
670 template<typename IE>
671 bool operator()(IE const& ie)
673 Element<IE>::run(ie, m_ctx);
674 return static_cast<bool>(m_ctx);
680 struct ChoiceVisitorDecoder
682 ChoiceVisitorDecoder(DecoderCtx& ctx, tag_value_t tag) : m_ctx(ctx), m_tag(tag) {}
684 template<typename IE> bool operator()(IE& ie)
686 Element<IE>::run(ie, m_ctx, &m_tag);
687 return static_cast<bool>(m_ctx);
695 struct ElementType<IE, std::enable_if_t<IE::ie_type == element_type::T_CHOICE && IE::asn_identifier_t::class_type == class_type_t::UNSPECIFIED> >
699 Selector(tag_value_t tag) : m_tag(tag) {}
701 template<typename ELM> void operator()(size_t idx)
703 if(!m_valid && Element<ELM>::is_matched(m_tag))
710 size_t get_idx() const {return m_index;}
711 bool is_valid() const {return m_valid;}
716 bool m_valid {false};
719 static bool inline is_matched(tag_value_t tag)
721 Selector selector {tag};
722 IE::enumerate(selector);
723 return selector.is_valid();
726 static void inline run(IE const& ie, EncoderCtx& ctx)
728 ChoiceVisitorEncoder ve(ctx);
730 if(ctx && !ie.encode(ve))
731 ctx.refErrorCtx().tagError(ie.get_index());
733 static void inline run(IE& ie, DecoderCtx& ctx, tag_value_t tag)
737 Selector selector {tag};
738 IE::enumerate(selector);
740 if(!selector.is_valid())
741 ctx.refErrorCtx().tagError(static_cast<uint32_t>(tag));
744 ChoiceVisitorDecoder vd {ctx, tag};
745 if(ctx && !ie.decode(selector.get_idx(), vd))
746 ctx.refErrorCtx().tagError(ie.get_index());
752 struct ElementType<IE, std::enable_if_t<IE::ie_type == element_type::T_CHOICE && IE::asn_identifier_t::class_type != class_type_t::UNSPECIFIED> >
754 static bool inline is_matched(tag_value_t _tag) {return ExplicitCodec<IE>::is_matched(_tag);}
756 static void inline run(IE const& ie, EncoderCtx& ctx)
758 ExplicitCodec<IE>::run(ie, ctx);
761 static void inline run(IE& ie, DecoderCtx& ctx, tag_value_t tag)
763 ExplicitCodec<IE>::run(ie, ctx, tag);
767 /***************************************************************************************
768 * IE_OBJECT_IDENTIFIER: Encoding the object identifier type
769 ***************************************************************************************/
771 struct ElementType<IE, std::enable_if_t<IE::ie_type == element_type::T_OBJECTIDENTIFIER> >
773 using tag_t = Tag<IE, false>;
775 static bool inline is_matched(tag_value_t _tag) {return _tag == tag_t::value();}
777 static void inline run(IE const& ie, EncoderCtx& ctx)
780 size_t length = ie.get().size();
781 Length::encode(length, ctx);
782 ctx.refBuffer().putBytes(ie.get().data(), length);
784 static void inline run(IE& ie, DecoderCtx& ctx, tag_value_t tag)
787 if(tag_t::value() == tag)
789 size_t length = Length::decode(ctx);
790 if(!length || length == indefinite_length)
792 ctx.refErrorCtx().sizeRangeError(length);
796 ASN_DECODER_TRACE("IE<type=%d name=%s tag=0x%x length=%zu> buffer: %s", static_cast<int>(IE::ie_type), IE::name(), static_cast<int>(tag), length, ctx.refBuffer().toString());
797 uint8_t const* data_in = ctx.refBuffer().getBytes(length);
800 ie.set(length, data_in);
806 ctx.refErrorCtx().tagError(static_cast<uint32_t>(tag));
811 /***************************************************************************************
813 ***************************************************************************************/
815 struct ElementType<IE, std::enable_if_t<IE::ie_type == element_type::T_OBJFIELD_FTV> >
817 using tag_t = Tag<IE, false>;
819 static bool inline is_matched(tag_value_t _tag) {return _tag == tag_t::value();}
822 /***************************************************************************************
824 ***************************************************************************************/
826 struct ElementType<IE, std::enable_if_t<IE::ie_type == element_type::T_OBJFIELD_TF> >
830 Selector(tag_value_t tag) : m_tag(tag) {}
832 template<typename ELM> void operator()(size_t idx)
834 if(Element<ELM>::is_matched(m_tag))
841 size_t get_idx() const {return m_index;}
842 bool is_valid() const {return m_valid;}
847 bool m_valid {false};
850 static bool inline is_matched(tag_value_t tag)
852 Selector selector(tag);
853 IE::enumerate(selector);
855 return selector.is_valid();
859 /***************************************************************************************
861 ***************************************************************************************/
862 template <class IE, class Enabler = void>
865 static bool inline is_matched(tag_value_t _tag)
867 return ElementType<IE>::is_matched(_tag);
870 static void inline run(IE const& ie, EncoderCtx& ctx)
872 ElementType<IE>::run(ie, ctx);
875 static void inline run(IE& ie, DecoderCtx& ctx, tag_value_t tag)
877 ElementType<IE>::run(ie, ctx, tag);
882 struct Identifier<IE, std::enable_if_t<IE::asn_identifier_t::tag_type == tag_type_t::EXPLICIT> >
884 static bool inline is_matched(tag_value_t _tag) {return ExplicitCodec<IE>::is_matched(_tag);}
886 static void inline run(IE const& ie, EncoderCtx& ctx)
888 ExplicitCodec<IE>::run(ie, ctx);
891 static void inline run(IE& ie, DecoderCtx& ctx, tag_value_t tag)
893 ExplicitCodec<IE>::run(ie, ctx, tag);
897 /***************************************************************************************
899 ***************************************************************************************/
903 static bool inline is_matched(tag_value_t _tag)
905 return Identifier<IE>::is_matched(_tag);
908 static void inline run(IE const& ie, EncoderCtx& ctx)
912 ASN_ENCODER_TRACE("IE<type=%d name=%s> buffer: %s", static_cast<int>(IE::ie_type), IE::name(), ctx.refBuffer().toString());
913 ctx.ie_name(IE::name());
914 Identifier<IE>::run(ie, ctx);
917 static void inline run(IE& ie, DecoderCtx& ctx, tag_value_t const* tag_ptr = nullptr)
921 ctx.ie_name(IE::name());
923 tag_value_t tag = tag_ptr ? *tag_ptr : get_tag(ctx);
925 Identifier<IE>::run(ie, ctx, tag);