commit 321d42e146f8efb3369f62ec4b6884668bc54d70
parent 66047667307d534d0586c30c322698f9aee2b797
Author: nolash <dev@holbrook.no>
Date: Sat, 10 Apr 2021 13:38:29 +0200
Add single length prefix list
Diffstat:
5 files changed, 157 insertions(+), 15 deletions(-)
diff --git a/src/rlp.c b/src/rlp.c
@@ -8,7 +8,7 @@
int rlp_init(rlp_encoder_t *encoder, int buffer_capacity) {
encoder->buf = malloc(buffer_capacity);
- encoder->depth = 0;
+ encoder->depth = -1;
encoder->ptr = encoder->buf;
}
@@ -23,6 +23,10 @@ int rlp_add(rlp_encoder_t *encoder, int len, char *data) {
int lenlen;
size_t r;
+ if (list_register(encoder) < 0) {
+ return -1;
+ }
+
r = (size_t)encoder->ptr;
if (len == 0) {
@@ -53,5 +57,40 @@ int rlp_add(rlp_encoder_t *encoder, int len, char *data) {
}
}
}
+
return (int)(r - (size_t)encoder->ptr);
-}
+}
+
+int rlp_descend(rlp_encoder_t *encoder, uint32_t num_items) {
+ encoder->depth++;
+// memcpy(&encoder->list_buf[encoder->depth], &num_items, sizeof(uint32_t));
+ encoder->list_buf[encoder->depth] = num_items + 1;
+ if (num_items < 56) {
+ *(encoder->ptr) = 0xc0 + num_items;
+ encoder->ptr++;
+ }
+ return encoder->depth + 1;
+}
+
+static int list_register(rlp_encoder_t *encoder) {
+ if (encoder->depth == -1) {
+ return 0;
+ }
+ encoder->list_buf[encoder->depth]--;
+ if (encoder->list_buf[encoder->depth] < 0) {
+ return -1;
+ } else if (encoder->list_buf[encoder->depth] == 0) {
+ encoder->depth--;
+ }
+ return encoder->depth + 1;
+}
+
+int rlp_finish(rlp_encoder_t *encoder) {
+ while (encoder->depth > -1) {
+ if (encoder->list_buf[encoder->depth] > 1) {
+ return -1;
+ }
+ list_register(encoder);
+ }
+ return 0;
+}
diff --git a/src/rlp.h b/src/rlp.h
@@ -6,7 +6,7 @@
#define RLP_MAX_LIST_DEPTH 1024
typedef struct rlp_encoder {
- uint32_t depth;
+ int depth;
uint32_t list_buf[RLP_MAX_LIST_DEPTH];
char *buf;
char *ptr;
@@ -17,7 +17,8 @@ int rlp_init(rlp_encoder_t *encoder, int buffer_capacity);
void rlp_free(rlp_encoder_t *encoder);
int rlp_descend(rlp_encoder_t *encoder, uint32_t num_items);
-static int rlp_ascend(rlp_encoder_t *encoder);
+static int list_register(rlp_encoder_t *encoder);
int rlp_add(rlp_encoder_t *encoder, int len, char *data);
+int rlp_finish(rlp_encoder_t *encoder);
#endif
diff --git a/tests/check_bits b/tests/check_bits
Binary files differ.
diff --git a/tests/check_rlp b/tests/check_rlp
Binary files differ.
diff --git a/tests/check_rlp.c b/tests/check_rlp.c
@@ -106,21 +106,123 @@ START_TEST(rlp_encode_long_bytes_with_length_test) {
}
END_TEST
+
+START_TEST(rlp_encode_list_descend_state_test) {
+ //char one = 42;
+ //char two = 13;
+ int r;
+
+ rlp_encoder_t encoder;
+ rlp_init(&encoder, 1024);
+
+ r = rlp_descend(&encoder, 2);
+ ck_assert_int_eq(1, r);
+ ck_assert_int_eq(encoder.depth, 0);
+ ck_assert_int_eq(encoder.list_buf[0], 3);
+
+ r = rlp_descend(&encoder, 4);
+ ck_assert_int_eq(2, r);
+ ck_assert_int_eq(encoder.depth, 1);
+ ck_assert_int_eq(encoder.list_buf[1], 5);
+
+ rlp_free(&encoder);
+}
+END_TEST
+
+
+START_TEST(rlp_encode_list_roundtrip_state_test) {
+ char one = 42;
+ char two = 13;
+ int r;
+
+ rlp_encoder_t encoder;
+ rlp_init(&encoder, 1024);
+
+ r = rlp_descend(&encoder, 2);
+ rlp_add(&encoder, 1, &one);
+ rlp_add(&encoder, 1, &two);
+ ck_assert_int_eq(encoder.depth, 0);
+ ck_assert_int_eq(encoder.list_buf[0], 1);
+
+ r = rlp_finish(&encoder);
+ ck_assert_int_eq(r, 0);
+ ck_assert_int_eq(encoder.depth, -1);
+ ck_assert_int_eq(encoder.list_buf[0], 0);
+
+ rlp_free(&encoder);
+}
+END_TEST
+
+
+START_TEST(rlp_encode_list_single_depth_test) {
+ char one = 42;
+ char two = 13;
+ char target[3] = {0xc2, 42, 13};
+ int r;
+
+ rlp_encoder_t encoder;
+ rlp_init(&encoder, 1024);
+
+ r = rlp_descend(&encoder, 2);
+ rlp_add(&encoder, 1, &one);
+ rlp_add(&encoder, 1, &two);
+ ck_assert_mem_eq(encoder.buf, target, 3);
+
+ rlp_free(&encoder);
+}
+END_TEST
+
+
+START_TEST(rlp_encode_list_two_depth_test) {
+ char one[2] = {42, 13};
+ char two[3] = {0x66, 0x6f, 0x6f};
+ char target[8] = {0xc2, 42, 13, 0xc1, 0x83, 0x66, 0x6f, 0x6f};
+ int r;
+
+ rlp_encoder_t encoder;
+ rlp_init(&encoder, 1024);
+
+ r = rlp_descend(&encoder, 2);
+ rlp_add(&encoder, 1, &one[0]);
+ rlp_add(&encoder, 1, &one[1]);
+ r = rlp_descend(&encoder, 1);
+ rlp_add(&encoder, 3, two);
+ ck_assert_mem_eq(encoder.buf, target, 8);
+
+ r = rlp_finish(&encoder);
+ ck_assert_int_eq(r, 0);
+
+ rlp_free(&encoder);
+}
+END_TEST
+
Suite *rlp_suite(void) {
Suite *s;
- TCase *tc;
+ TCase *tci;
+ TCase *tcb;
+ TCase *tcl;
s = suite_create("Rlp");
- tc = tcase_create("Init");
-
- tcase_add_test(tc, rlp_init_test);
- tcase_add_test(tc, rlp_encode_empty_byte_test);
- tcase_add_test(tc, rlp_encode_single_zero_byte_test);
- tcase_add_test(tc, rlp_encode_single_byte_test);
- tcase_add_test(tc, rlp_encode_single_byte_with_length_test);
- tcase_add_test(tc, rlp_encode_short_bytes_with_length_test);
- tcase_add_test(tc, rlp_encode_long_bytes_with_length_test);
- suite_add_tcase(s, tc);
+ tci = tcase_create("Init");
+ tcb = tcase_create("Bytes");
+ tcl = tcase_create("List");
+
+ tcase_add_test(tci, rlp_init_test);
+ suite_add_tcase(s, tci);
+
+ tcase_add_test(tcb, rlp_encode_empty_byte_test);
+ tcase_add_test(tcb, rlp_encode_single_zero_byte_test);
+ tcase_add_test(tcb, rlp_encode_single_byte_test);
+ tcase_add_test(tcb, rlp_encode_single_byte_with_length_test);
+ tcase_add_test(tcb, rlp_encode_short_bytes_with_length_test);
+ tcase_add_test(tcb, rlp_encode_long_bytes_with_length_test);
+ suite_add_tcase(s, tcb);
+
+ tcase_add_test(tcl, rlp_encode_list_descend_state_test);
+ tcase_add_test(tcl, rlp_encode_list_roundtrip_state_test);
+ tcase_add_test(tcl, rlp_encode_list_single_depth_test);
+ tcase_add_test(tcl, rlp_encode_list_two_depth_test);
+ suite_add_tcase(s, tcl);
return s;
}