public static Message convertBencodeToMessage (Value<?> value) {
        try {
            StringValue tVal = Bencode.getChildValue(value, StringValue.class, "t");
            StringValue yVal = Bencode.getChildValue(value, StringValue.class, "y");

            byte[] trid = tVal.getValue();
            MessageType type = MessageType.fromString(yVal.getStringValue());

            switch (type) {
                case ERROR: {
                    ListValue eVal = Bencode.getChildValue(value, ListValue.class, "e");
                    if (eVal.getSize() != 2) {
                        throw new IllegalArgumentException();
                    }
                    int eCode = Bencode.getChildValue(eVal, IntegerValue.class, "0").getValue().intValue();
                    String eMsg = Bencode.getChildValue(eVal, StringValue.class, "1").getStringValue();
                    return new ErrorMessage(trid, eCode, eMsg);
                }

                case QUERY: {
                    StringValue qVal = Bencode.getChildValue(value, StringValue.class, "q");
                    DictionaryValue aVal = Bencode.getChildValue(value, DictionaryValue.class, "a");
                    return new QueryMessage(trid, QueryType.fromString(qVal.getStringValue()), aVal);
                }

                case RESPONSE: {
                    DictionaryValue rVal = Bencode.getChildValue(value, DictionaryValue.class, "r");
                    return new ResponseMessage(trid, rVal);
                }

                default: {
                    throw new IllegalArgumentException();
                }
            }
        } catch (Exception e) {
            // If something goes wrong, throw an IAE
            throw new IllegalArgumentException(e);
        }
    }