0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-05-28 15:53:46 +02:00

ircd::b64: Add encoding diction parameter; remove converters; reorg interface.

This commit is contained in:
Jason Volk 2020-08-10 05:14:43 -07:00
parent 486d9c1133
commit 44bd60ea08
5 changed files with 58 additions and 78 deletions

View file

@ -13,29 +13,46 @@
namespace ircd::b64
{
[[gnu::aligned(64)]]
extern const u8
dict_rfc1421[64], // [62] = '+', [63] = '/'
dict_rfc3501[64], // [62] = '+', [63] = ','
dict_rfc4648[64]; // [62] = '-', [63] = '_'
// Binary -> Base64 conversion suite
constexpr size_t encode_size(const size_t &) noexcept;
size_t encode_size(const const_buffer &in) noexcept;
string_view encode(const mutable_buffer &out, const const_buffer &in) noexcept;
static const auto
&standard { dict_rfc1421 },
&mailbox { dict_rfc3501 },
&urlsafe { dict_rfc4648 };
// Binary -> Base64 conversion without padding
constexpr size_t encode_unpadded_size(const size_t &) noexcept;
size_t encode_unpadded_size(const const_buffer &in) noexcept;
string_view encode_unpadded(const mutable_buffer &out, const const_buffer &in) noexcept;
// Base64 -> Binary conversion (padded or unpadded)
constexpr size_t decode_size(const size_t &) noexcept;
constexpr size_t encode_size(const size_t &) noexcept;
constexpr size_t encode_unpadded_size(const size_t &) noexcept;
size_t decode_size(const string_view &in) noexcept;
size_t encode_size(const const_buffer &in) noexcept;
size_t encode_unpadded_size(const const_buffer &in) noexcept;
const_buffer decode(const mutable_buffer &out, const string_view &in);
// Base64 convenience conversions
string_view tob64url(const mutable_buffer &out, const string_view &in) noexcept;
string_view urltob64(const mutable_buffer &out, const string_view &in) noexcept;
template<const u8 (&dict)[64] = standard>
string_view encode(const mutable_buffer &out, const const_buffer &in) noexcept;
template<const u8 (&dict)[64] = standard>
string_view encode_unpadded(const mutable_buffer &out, const const_buffer &in) noexcept;
}
inline size_t
ircd::b64::encode_unpadded_size(const const_buffer &in)
noexcept
{
return encode_unpadded_size(size(in));
}
inline size_t
ircd::b64::encode_size(const const_buffer &in)
noexcept
{
return encode_size(size(in));
}
inline size_t
@ -45,20 +62,6 @@ noexcept
return decode_size(size(in));
}
constexpr size_t
ircd::b64::decode_size(const size_t &in)
noexcept
{
return (in * 0.75) + 1; //XXX: constexpr ceil()
}
inline size_t
ircd::b64::encode_unpadded_size(const const_buffer &in)
noexcept
{
return encode_unpadded_size(size(in));
}
constexpr size_t
ircd::b64::encode_unpadded_size(const size_t &in)
noexcept
@ -66,16 +69,16 @@ noexcept
return (in * (4.0 / 3.0)) + 1; //XXX: constexpr ceil()
}
inline size_t
ircd::b64::encode_size(const const_buffer &in)
noexcept
{
return encode_size(size(in));
}
constexpr size_t
ircd::b64::encode_size(const size_t &in)
noexcept
{
return ((in * (4.0 / 3.0)) + 1) + (3 - in % 3) % 3; //XXX: constexpr ceil
}
constexpr size_t
ircd::b64::decode_size(const size_t &in)
noexcept
{
return (in * 0.75) + 1; //XXX: constexpr ceil()
}

View file

@ -24,6 +24,7 @@ namespace ircd::b64
encode_permute_tab[64],
encode_shift_ctrl[64];
template<const u8 (&dict)[64]>
static u8x64 encode_block(const u8x64 in) noexcept;
}
#pragma GCC visibility pop
@ -85,36 +86,9 @@ ircd::b64::encode_shift_ctrl
(10 + 0), ( 4 + 0), (22 + 0), (16 + 0), (10 + 32), ( 4 + 32), (22 + 32), (16 + 32),
};
//
// Conversion convenience suite
//
ircd::string_view
ircd::b64::urltob64(const mutable_buffer &out,
const string_view &in)
noexcept
{
//TODO: optimize with single pass
string_view ret(in);
ret = replace(out, ret, '-', '+');
ret = replace(out, ret, '_', '/');
return ret;
}
ircd::string_view
ircd::b64::tob64url(const mutable_buffer &out,
const string_view &in)
noexcept
{
//TODO: optimize with single pass
string_view ret(in);
ret = replace(out, ret, '+', '-');
ret = replace(out, ret, '/', '_');
return ret;
}
/// Encoding in to base64 at out. Out must be 1.33+ larger than in
/// padding is not present in the returned view.
template<const ircd::u8 (&dict)[64]>
ircd::string_view
ircd::b64::encode(const mutable_buffer &out,
const const_buffer &in)
@ -127,7 +101,7 @@ noexcept
const auto encoded
{
encode_unpadded(out, in)
encode_unpadded<dict>(out, in)
};
assert(size(encoded) + pads <= size(out));
@ -143,8 +117,11 @@ noexcept
data(out), len
};
}
template ircd::string_view ircd::b64::encode<ircd::b64::standard>(const mutable_buffer &, const const_buffer &) noexcept;
template ircd::string_view ircd::b64::encode<ircd::b64::urlsafe>(const mutable_buffer &, const const_buffer &) noexcept;
/// Encoding in to base64 at out. Out must be 1.33+ larger than in.
template<const ircd::u8 (&dict)[64]>
ircd::string_view
ircd::b64::encode_unpadded(const mutable_buffer &out,
const const_buffer &in)
@ -166,16 +143,16 @@ noexcept
// Destination is indexed at 64 byte stride
const auto di
{
reinterpret_cast<u512x1_u *>(data(out) + (i * 64))
reinterpret_cast<u512x1_u *__restrict__>(data(out) + (i * 64))
};
// Source is indexed at 48 byte stride
const auto si
{
reinterpret_cast<const u512x1_u *>(data(in) + (i * 48))
reinterpret_cast<const u512x1_u *__restrict__>(data(in) + (i * 48))
};
*di = encode_block(*si);
*di = encode_block<dict>(*si);
}
for(; i * 48 < size(in); ++i)
@ -184,7 +161,7 @@ noexcept
for(j = 0; i * 48 + j < size(in); ++j)
block[j] = in[i * 48 + j];
block = encode_block(block);
block = encode_block<dict>(block);
for(j = 0; i * 64 + j < out_len; ++j)
out[i * 64 + j] = block[j];
}
@ -194,6 +171,8 @@ noexcept
data(out), out_len
};
}
template ircd::string_view ircd::b64::encode_unpadded<ircd::b64::standard>(const mutable_buffer &, const const_buffer &) noexcept;
template ircd::string_view ircd::b64::encode_unpadded<ircd::b64::urlsafe>(const mutable_buffer &, const const_buffer &) noexcept;
/// Returns 64 base64-encoded characters from 48 input characters. For any
/// inputs less than 48 characters trail with null characters; caller computes
@ -206,15 +185,11 @@ noexcept
/// Based on https://arxiv.org/pdf/1910.05109 (and earlier work). No specific
/// intrinsics are used here; instead we recite a kotodama divination known
/// as "vector extensions" which by chance is visible to humans as C syntax.
template<const ircd::u8 (&dict)[64]>
ircd::u8x64
ircd::b64::encode_block(const u8x64 in)
noexcept
{
static const auto &dict
{
dict_rfc1421
};
size_t i, j, k;
// vpermb

View file

@ -113,7 +113,7 @@ ircd::m::make_id(const event &event,
{
const id::event ret
{
buf, b64::tob64url(readable, b64::encode_unpadded(readable, hash)), at<"origin"_>(event)
buf, b64::encode_unpadded<b64::urlsafe>(readable, hash), at<"origin"_>(event)
};
buf.assigned(ret);
@ -132,7 +132,7 @@ ircd::m::make_id(const event &event,
const id::event ret
{
buf, b64::tob64url(readable, b64::encode_unpadded(readable, hash)), string_view{}
buf, b64::encode_unpadded<b64::urlsafe>(readable, hash), string_view{}
};
buf.assigned(ret);

View file

@ -862,9 +862,11 @@ ircd::m::id::event::v4::v4(const mutable_buffer &out,
};
out[0] = '$';
string_view hashb64;
hashb64 = b64::encode_unpadded(out + 1, hash);
hashb64 = b64::tob64url(out + 1, hashb64);
const string_view hashb64
{
b64::encode_unpadded<b64::urlsafe>(out + 1, hash)
};
return string_view
{
ircd::data(out), 1 + ircd::size(hashb64)

View file

@ -33,7 +33,7 @@ ircd::m::user::filter::set(const mutable_buffer &idbuf,
const string_view filter_id
{
b64::tob64url(idbuf, b64::encode_unpadded(idbuf, hash))
b64::encode_unpadded<b64::urlsafe>(idbuf, hash)
};
//TODO: ABA