Datum convert_element<int>(PG_FUNCTION_ARGS, const mongo::BSONElement e)
{
    if(e.type() == mongo::NumberInt)
    {
        PG_RETURN_INT32(e._numberInt());
    }
    else
    {
        throw convertion_error("int4");
    }
}
Datum convert_element<std::string>(PG_FUNCTION_ARGS, const mongo::BSONElement e)
{
    std::stringstream ss;
    switch(e.type())
    {
        case mongo::String:
        case mongo::DBRef:
        case mongo::Symbol:
            return return_string(std::string(e.valuestr(), e.valuestrsize()-1));

        case mongo::NumberDouble:
            ss << e._numberDouble();
            break;

        case mongo::jstOID:
            ss << e.__oid().str();
            break;

        case mongo::Bool:
            ss << std::boolalpha << e.boolean();
            break;

        case mongo::Date:
            return return_string(
                to_iso_extended_string(
                    boost::posix_time::ptime(
                        boost::gregorian::date(1970, 1, 1),
                        boost::posix_time::milliseconds(e.date().millis)
                        )
                    )
                );

        case mongo::RegEx:
            ss << e.regex();
            break;

        case mongo::NumberInt:
            ss << e._numberInt();
            break;

        case mongo::NumberLong:
            ss << e._numberLong();
            break;

        default:
            throw convertion_error("text");

    }
    return return_string(ss.str());
}
Datum convert_element<int64>(PG_FUNCTION_ARGS, const mongo::BSONElement e)
{
    switch(e.type())
    {
        case mongo::NumberLong:
            PG_RETURN_INT64(e._numberLong());

        // this conversion has to be imlicitly allowedm, otherwise defining object form json would be pain int the ass
        case mongo::NumberInt:
            PG_RETURN_INT64(static_cast<int64>(e._numberInt()));

        default:
            throw convertion_error("int8");
    }
}