code: private EConvResult transConv(byte[] in, Ptr inPtr, int inStop, byte[] out, Ptr outPtr, int outStop, int flags, Ptr resultPositionPtr) {
          // null check
  
          if (elements[0].lastResult == EConvResult.AfterOutput) elements[0].lastResult = EConvResult.SourceBufferEmpty;
  
          for (int i = numTranscoders - 1; 0 <= i; i--) {
              switch (elements[i].lastResult) {
              case InvalidByteSequence:
              case IncompleteInput:
              case UndefinedConversion:
              case AfterOutput:
              case Finished:
                  return transConvNeedReport(in, inPtr, inStop, out, outPtr, outStop, flags, resultPositionPtr, i + 1, i);
              case DestinationBufferFull:
              case SourceBufferEmpty:
                  break;
              default:
                  throw new InternalException("unexpected transcode last result");
              }
          }
  
          /* /^[sd]+$/ is confirmed. but actually /^s*d*$/. */
  
          if (elements[numTranscoders - 1].lastResult == EConvResult.DestinationBufferFull && (flags & AFTER_OUTPUT) != 0) {
              EConvResult res = transConv(NULL_STRING, Ptr.NULL, 0, out, outPtr, outStop, (flags & ~AFTER_OUTPUT) | PARTIAL_INPUT, resultPositionPtr);
              return res.isSourceBufferEmpty() ? EConvResult.AfterOutput : res;
          }
  
          return transConvNeedReport(in, inPtr, inStop, out, outPtr, outStop, flags, resultPositionPtr, 0, -1);
      }
docs: /* rb_trans_conv