#pragma once namespace saw { namespace encode { struct Base64 {}; } template<> class data { public: using Schema = schema::String; private: std::string data_; public: data() = default; data(std::string data__): data_{std::move(data__)} {} uint64_t size() const { return data_.size(); } char& at(uint64_t i){ return data_.at(i); } const char& at(uint64_t i) const { return data_.at(i); } std::string stl_string() const { return data_; } bool operator==(const data& rhs) const { return data_ == rhs.data_; } }; namespace impl { constexpr char base64_char_map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; } template<> class codec { public: using Schema = schema::String; private: public: template static error_or encode(const data& from, data& to){ std::string b64_str; try { uint64_t unpadded_len = (from.size() * 4u + 2u) / 3u; uint64_t padded_len = ( unpadded_len + 3u ) & ~3u; b64_str.resize(padded_len); }catch(const std::exception&){ return make_error(); } uint64_t j{0u}, k{0u}; std::array s{}; for(uint64_t i = 0u; i < from.size(); ++i){ s[j] = from.at(i); ++j; if(j==3){ b64_str.at(k) = impl::base64_char_map[(s[0u] & 0xFC) >> 2]; b64_str.at(k+1u) = impl::base64_char_map[((s[0u] & 0x03) << 4) | ((s[1] & 0xF0) >> 4)]; b64_str.at(k+2u) = impl::base64_char_map[((s[1u] & 0x0F) << 2) | ((s[2] & 0xC0) >> 6)]; b64_str.at(k+3u) = impl::base64_char_map[(s[2u] & 0x3F)]; j = 0u; k+=4u; } } if(j > 0){ if( j == 1u ){ s[1u] = 0u; } b64_str.at(k+0u) = impl::base64_char_map[(s[0u] & 0xFF) >> 2]; b64_str.at(k+1u) = impl::base64_char_map[((s[0u] & 0x03)<<4) + ((s[1u]&0xF0)>>4)]; if(j == 2u){ b64_str[k+2u] = impl::base64_char_map[ ((s[1u]&0x0F)<<2) ]; }else { b64_str[k+2u] = '='; } b64_str[k+3u] = '='; } to = {std::move(b64_str)}; return void_t{}; } template static error_or decode(data& from, data& to){ (void) to; (void) from; return make_error(); } }; }