public DataType decodeDataType(Decoder decoder) throws DecoderException {
		int el = decoder.openElement();
		if (el == ELEM_VOID.id()) {
			decoder.closeElement(el);
			return voidDt;
		}
		String name = "";
		long id = 0;
		for (;;) {
			int attribId = decoder.getNextAttributeId();
			if (attribId == 0) {
				break;
			}
			if (attribId == ATTRIB_NAME.id()) {
				name = decoder.readString();
			}
			else if (attribId == ATTRIB_ID.id()) {
				id = decoder.readUnsignedInteger();
			}
		}
		if (el == ELEM_TYPEREF.id()) {
			decoder.closeElement(el);
			return findBaseType(name, id);
		}
		if (el == ELEM_DEF.id()) {
			decoder.closeElementSkipping(el);
			return findBaseType(name, id);
		}
		if (el != ELEM_TYPE.id()) {
			throw new DecoderException("Expecting <type> element");
		}

		if (name.length() != 0) {
			decoder.closeElementSkipping(el);
			return findBaseType(name, id);
		}
		String meta = decoder.readString(ATTRIB_METATYPE);
		DataType restype = null;
		if (meta.equals("ptr")) {
			int size = (int) decoder.readSignedInteger(ATTRIB_SIZE);
			if (decoder.peekElement() != 0) {
				DataType dt = decodeDataType(decoder);
				boolean useDefaultSize = (size == dataOrganization.getPointerSize() ||
					size > PointerDataType.MAX_POINTER_SIZE_BYTES);
				restype = new PointerDataType(dt, useDefaultSize ? -1 : size, progDataTypes);
			}
		}
		else if (meta.equals("array")) {
			int arrsize = (int) decoder.readSignedInteger(ATTRIB_ARRAYSIZE);
			if (decoder.peekElement() != 0) {
				DataType dt = decodeDataType(decoder);
				if (dt == null || dt.getLength() == 0) {
					dt = DataType.DEFAULT;
				}
				restype = new ArrayDataType(dt, arrsize, dt.getLength(), progDataTypes);
			}
		}
		else if (meta.equals("spacebase")) {		// Typically the type of "the whole stack"
			decoder.closeElementSkipping(el);  		// get rid of unused "addr" element
			return voidDt;
		}
		else if (meta.equals("struct")) {
			// We reach here if the decompiler invents a structure, apparently
			// this is a band-aid so that we don't blow up
			// just make an undefined data type of the appropriate size
			int size = (int) decoder.readSignedInteger(ATTRIB_SIZE);
			decoder.closeElementSkipping(el);
			return Undefined.getUndefinedDataType(size);
		}
		else if (meta.equals("int")) {
			int size = (int) decoder.readSignedInteger(ATTRIB_SIZE);
			decoder.closeElement(el);
			return AbstractIntegerDataType.getSignedDataType(size, progDataTypes);
		}
		else if (meta.equals("uint")) {
			int size = (int) decoder.readSignedInteger(ATTRIB_SIZE);
			decoder.closeElement(el);
			return AbstractIntegerDataType.getUnsignedDataType(size, progDataTypes);
		}
		else if (meta.equals("float")) {
			int size = (int) decoder.readSignedInteger(ATTRIB_SIZE);
			decoder.closeElement(el);
			// NOTE: Float lookup by length must use "raw" encoding size since
			return AbstractFloatDataType.getFloatDataType(size, progDataTypes);
		}
		else if (meta.equals("partunion")) {
			int size = (int) decoder.readSignedInteger(ATTRIB_SIZE);
			int offset = (int) decoder.readSignedInteger(ATTRIB_OFFSET);
			DataType dt = decodeDataType(decoder);
			decoder.closeElement(el);
			return new PartialUnion(progDataTypes, dt, offset, size);
		}
		else if (meta.equals("partenum")) {
			int size = (int) decoder.readSignedInteger(ATTRIB_SIZE);
//			int offset = (int) decoder.readSignedInteger(ATTRIB_OFFSET);
//			DataType dt = decodeDataType(decoder);
			decoder.closeElementSkipping(el);
			return AbstractIntegerDataType.getUnsignedDataType(size, progDataTypes);
		}
		else {	// We typically reach here if the decompiler invents a new type
				// probably an unknown with a non-standard size
			int size = (int) decoder.readSignedInteger(ATTRIB_SIZE);
			decoder.closeElementSkipping(el);
			return Undefined.getUndefinedDataType(size).clone(progDataTypes);
		}
		if (restype == null) {
			throw new DecoderException("Unable to resolve DataType");
		}
		decoder.closeElementSkipping(el);
		return restype;
	}
Decode a data-type from the stream
@param decoder is the stream decoder
@return the decoded data-type object
@throws DecoderException for invalid encodings
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java