summaryrefslogtreecommitdiff
path: root/modules/codec/c++/transport.hpp
blob: bc58937df3cb7aaec00a47dc9bcc78b586449969 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#pragma once

#include <forstio/buffer.hpp>
#include "data.hpp"

namespace saw {
namespace trans {
template<uint64_t Len = 8u>
struct FixedLength {};

template<uint64_t Len = 8u>
struct VarLength {};

struct NewLine {};
struct CarriageReturnNewLine {};
}

template<typename T>
class transport;

template<uint64_t Len>
class transport<trans::FixedLength<Len>> final {
private:
public:
	error_or<buffer_view> view_slice(buffer& buff) const {
		typename native_data_type<schema::Primitive<schema::UnsignedInteger, Len>>::type val{};
		buffer_view view{buff};

		auto eov = stream_value<schema::Primitive<schema::UnsignedInteger, Len>>::decode(val, view);
		if(eov.is_error()){
			return std::move(eov.get_error());
		}

		if(view.read_composite_length() < val){
			return make_error<err::buffer_exhausted>();
		}
		buff.read_advance(Len);

		buffer_view data_view{buff, val, 0u};
		return data_view;
	}

	error_or<uint64_t> wrap(buffer& out_buff, buffer& in_buff){
		using trans_type = typename native_data_type<schema::Primitive<schema::UnsignedInteger, Len>>::type;
		trans_type val{};
		val = static_cast<trans_type>(in_buff.read_composite_length());

		auto eov = stream_value<schema::Primitive<schema::UnsignedInteger, Len>>::encode(val, out_buff);
		if(eov.is_error()){
			auto& err = eov.get_error();
			return std::move(err);
		}

		return Len;
	}

	error_or<array_buffer> chain_slice(chain_array_buffer& buff) const {
		(void) buff;
		return make_error<err::not_implemented>();
	}
};

template<uint64_t Len>
class transport<trans::VarLength<Len>> final {
public:
	error_or<buffer_view> view_slice(buffer& buff) const {
		using var_max_t = typename native_data_type<schema::Primitive<schema::UnsignedInteger, Len>>::type;
		var_max_t val{};
		buffer_view view{buff};

		std::array<uint8_t,Len> val_array;

		for(uint64_t i = 0; i < Len && view.read_composite_length() > 0u; ++i){
			uint8_t len_byte = view.read();
			val |= static_cast<var_max_t>(len_byte & 0x7F) << i*7;

			if( (len_byte & 0x80 ) == 0 ){
				if( (i+1u) == Len ) {
					return make_error<err::invalid_state>("Last VarLength Continue Bit is set.");
				}
			}

			view.read_advance(1u);
		}

		if( val > view.read_composite_length() ){
			return make_error<err::buffer_exhausted>();
		}

		return buffer_view{buff, val, 0u};
	}

	error_or<uint64_t> wrap(buffer& out_buff, buffer& in_buff){
		using var_max_t = typename native_data_type<schema::Primitive<schema::UnsignedInteger, Len>>::type;

		uint64_t len = in_buff.read_composite_length();
		var_max_t val = len;
		if(len != val){
			return make_error<err::invalid_state>("Number too large");
		}

		buffer_view view{out_buff};
		uint64_t i = 0u;
		for(i = 0u; i < Len && view.write_composite_length() > 0u; ++i){
			view.write() = (val & 0x7F);
			
			if( ( val & ~0x7F ) == 0u ){
				++i;
				break;
			}

			view.write() |= 0x80;

			val = (val >> (i * 7u));
			view.write_advance(1u);
		}

		return i;
	}

	error_or<array_buffer> chain_slice(chain_array_buffer& buff) const {
		(void) buff;
		return make_error<err::not_implemented>();
	}
};
}