void Parser::scan_value(void) {
    int c = read_byte();
    switch (c) {
    case trace::TYPE_NULL:
    case trace::TYPE_FALSE:
    case trace::TYPE_TRUE:
        break;
    case trace::TYPE_SINT:
        scan_sint();
        break;
    case trace::TYPE_UINT:
        scan_uint();
        break;
    case trace::TYPE_FLOAT:
        scan_float();
        break;
    case trace::TYPE_DOUBLE:
        scan_double();
        break;
    case trace::TYPE_STRING:
        scan_string();
        break;
    case trace::TYPE_ENUM:
        scan_enum();
        break;
    case trace::TYPE_BITMASK:
        scan_bitmask();
        break;
    case trace::TYPE_ARRAY:
        scan_array();
        break;
    case trace::TYPE_STRUCT:
        scan_struct();
        break;
    case trace::TYPE_BLOB:
        scan_blob();
        break;
    case trace::TYPE_OPAQUE:
        scan_opaque();
        break;
    case trace::TYPE_REPR:
        scan_repr();
        break;
    case trace::TYPE_WSTRING:
        scan_wstring();
        break;
    default:
        std::cerr << "error: unknown type " << c << "\n";
        exit(1);
    case -1:
        break;
    }
}
void scan_result_response(const char** src, const char* max, HV *out) {
    I32 r;
    SV *sv;

    scan_enum(src, max, &r);
    hv_stores(out, "result", newSVsv(ldap_error2sv_noinc(r)));

    sv = newSV(0);
    hv_stores(out, "matched_dn", sv);
    scan_string_utf8(src, max, sv);

    sv = newSV(0);
    hv_stores(out, "message", sv);
    scan_string_utf8(src, max, sv);

    if (*src < max) {
	U8 type;
	U32 tag;
	STRLEN len;
	AV *referrals;
	scan_tag(src, max, &type, &tag);
	if (type != (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED) || tag != 3)
	    croak("bad packed data");
	scan_length(src, max, &len);
	if (len != max - *src)
	    croak("scan_result_response: packet too short");

	referrals = newAV();
	hv_stores(out, "referrals", newRV_noinc((SV*)referrals));

	while (*src < max) {
	    SV *v = newSV(0);
	    av_push(referrals, v);
	    scan_string_utf8(src, max, v);
	}
    }
}