public CliSigType readCliType(BinaryReader reader) throws IOException, InvalidInputException {
		byte typeByte = reader.readNextByte();
		CliElementType typeCode = CliElementType.fromInt(typeByte);
		if (typeCode == null) {
			throw new InvalidInputException("TypeCode not found at reader index " +
				reader.getPointerIndex() + ". Are you in the right place? (" + typeByte + ")");
		}
		switch (typeCode) {
			case ELEMENT_TYPE_ARRAY:
				return new CliTypeArray(reader, typeCode);

			case ELEMENT_TYPE_CLASS:
				return new CliTypeClass(reader, typeCode);

			case ELEMENT_TYPE_FNPTR:
				return new CliTypeFnPtr(reader, typeCode);

			case ELEMENT_TYPE_GENERICINST:
				return new CliTypeGenericInst(reader, typeCode);

			case ELEMENT_TYPE_MVAR:
			case ELEMENT_TYPE_VAR:
				return new CliTypeVarOrMvar(reader, typeCode);

			case ELEMENT_TYPE_PTR:
				return new CliTypePtr(reader, typeCode);

			case ELEMENT_TYPE_SZARRAY: // Single dimensional, zero-based array, e.g. a vector
				return new CliTypeSzArray(reader, typeCode);

			case ELEMENT_TYPE_VALUETYPE:
				return new CliTypeValueType(reader, typeCode);

			default:
				// Other types: nothing follows
				return new CliTypePrimitive(typeCode);
		}
	}
This is the method that subclasses should override. If stream is null, the method must not cause a NullPointerException,
i.e. it must handle this as if there was no stream to begin with.
Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/cli/blobs/CliAbstractSig.java