func decode_door(t *testing.T, rd *stream.Stream, last int, door *pbDoor) {
	rd.Seek(0, 0)
	d := binutil.NewProtobufDecoder(rd)
	posidx := 0
	for rd.Position() < last {
		_, tag, wire, _ := d.Tag()
		switch tag {
		case 0:
			t.Fatalf("test protobuf decode: got tag 0 when parse door\n")
		case 1:
			_, door.I32, _ = d.Int32()
		case 3:
			_, door.S32, _ = d.Sint32()
		case 5:
			_, door.D32, _ = d.Sfixed32()
		case 2:
			_, door.I64, _ = d.Int64()
		case 4:
			_, door.S64, _ = d.Sint64()
		case 6:
			_, door.D64, _ = d.Sfixed64()

		case 10:
			_, door.U32, _ = d.Uint32()
		case 12:
			_, door.X32, _ = d.Fixed32()
		case 11:
			_, door.U64, _ = d.Uint64()
		case 13:
			_, door.X64, _ = d.Fixed64()

		case 20:
			_, door.F32, _ = d.Float32()
		case 21:
			_, door.F64, _ = d.Float64()

		case 30:
			_, door.B, _ = d.Bool()
		case 31:
			_, door.S, _ = d.String()
		case 32:
			_, door.E, _ = d.Enum()
		case 40:
			_, u, _ := d.Uint64()
			m, L := int64(u), int(u)
			dm.SetSize(m)
			d.GetBody(dm.Buf()[:m])
			decode_pos(t, dm, L, &door.Poslist[posidx])
			if dm.Position() != L {
				t.Fatalf("test protobuf decode: got pos fail\n")
			}
			posidx++
		default:
			d.Skip(wire)
		}
	}
	if rd.Position() != last {
		t.Fatalf("test protobuf decode: parse pos, error tail position\n")
	}
}
func decode_pos(t *testing.T, rd *stream.Stream, last int, pos *pbPos) {
	rd.Seek(0, 0)
	d := binutil.NewProtobufDecoder(rd)
	for rd.Position() < last {
		_, tag, wire, _ := d.Tag()
		switch tag {
		case 0:
			t.Fatalf("test protobuf decode: got tag 0 when parse pos\n")
		case 1:
			_, pos.X, _ = d.Int32()
		case 2:
			_, pos.Y, _ = d.Int32()
		default:
			d.Skip(wire)
		}
	}
	if rd.Position() != last {
		t.Fatalf("test protobuf decode: parse pos, error tail position\n")
	}
}