public static Varnode decode(Decoder decoder, PcodeFactory factory) throws DecoderException {
		int el = decoder.peekElement();
		if (el == ELEM_VOID.id()) {
			decoder.openElement();
			decoder.closeElement(el);
			return null;
		}
		else if (el == ELEM_SPACEID.id() || el == ELEM_IOP.id()) {
			Address addr = AddressXML.decode(decoder);
			return factory.newVarnode(4, addr);
		}

		el = decoder.openElement();
		int ref = -1;
		int sz = 4;
		for (;;) {
			int attribId = decoder.getNextAttributeId();
			if (attribId == 0) {
				break;
			}
			else if (attribId == ATTRIB_REF.id()) {	// If we have a reference
				ref = (int) decoder.readUnsignedInteger();
				Varnode vn = factory.getRef(ref);				// The varnode may already exist
				if (vn != null) {
					decoder.closeElement(el);
					return vn;
				}
			}
			else if (attribId == ATTRIB_SIZE.id()) {
				sz = (int) decoder.readSignedInteger();
			}
		}
		decoder.rewindAttributes();
		Varnode vn;
		Address addr = AddressXML.decodeFromAttributes(decoder);
		AddressSpace spc = addr.getAddressSpace();
		if ((spc != null) && (spc.getType() == AddressSpace.TYPE_VARIABLE)) {	// Check for a composite Address
			decoder.rewindAttributes();
			try {
				Join join = decodePieces(decoder);
				VariableStorage storage = factory.getJoinStorage(join.pieces);
				// Update "join" address to the one just registered with the pieces
				addr = factory.getJoinAddress(storage);
				// Update size to be the size of the pieces 
				sz = join.logicalSize;
			}
			catch (InvalidInputException e) {
				throw new DecoderException("Invalid varnode pieces: " + e.getMessage());
			}
		}
		if (ref != -1) {
			vn = factory.newVarnode(sz, addr, ref);
		}
		else {
			vn = factory.newVarnode(sz, addr);
		}
		decoder.rewindAttributes();
		for (;;) {
			int attribId = decoder.getNextAttributeId();
			if (attribId == 0) {
				break;
			}
			else if (attribId == ATTRIB_GRP.id()) {
				short val = (short) decoder.readSignedInteger();
				factory.setMergeGroup(vn, val);
			}
			else if (attribId == ATTRIB_PERSISTS.id()) {
				if (decoder.readBool()) {
					factory.setPersistent(vn, true);
				}
			}
			else if (attribId == ATTRIB_ADDRTIED.id()) {
				if (decoder.readBool()) {
					factory.setAddrTied(vn, true);
				}
			}
			else if (attribId == ATTRIB_UNAFF.id()) {
				if (decoder.readBool()) {
					factory.setUnaffected(vn, true);
				}
			}
			else if (attribId == ATTRIB_INPUT.id()) {
				if (decoder.readBool()) {
					vn = factory.setInput(vn, true);
				}
			}
			else if (attribId == ATTRIB_VOLATILE.id()) {
				if (decoder.readBool()) {
					factory.setVolatile(vn, true);
				}
			}
		}
		decoder.closeElement(el);
		return vn;
	}
Decode a Varnode from a stream

@param decoder is the stream decoder
@param factory pcode factory used to create valid pcode
@return the new Varnode
@throws DecoderException if the Varnode is improperly encoded
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java