Line data Source code
1 : #include "fd_shred.h" 2 : #include "fd_deshredder.h" 3 : 4 : void 5 : fd_deshredder_init( fd_deshredder_t * shredder, 6 : void * buf, 7 : ulong bufsz, 8 : fd_shred_t const ** shreds, 9 0 : ulong shred_cnt ) { 10 0 : shredder->shreds = shreds; 11 0 : shredder->shred_cnt = (uint)shred_cnt; 12 0 : shredder->data_off = 0U; 13 0 : shredder->buf = buf; 14 0 : shredder->bufsz = bufsz; 15 0 : shredder->result = -FD_SHRED_EPIPE; 16 0 : } 17 : 18 : long 19 0 : fd_deshredder_next( fd_deshredder_t * const shredder ) { 20 : /* Remember start of provided buffer */ 21 0 : uchar * const orig_buf = shredder->buf; 22 : 23 : /* Consume shreds, appending each shred buffer into entry buffer */ 24 0 : for(;;) { 25 : /* Sanity check: No unexpected "end of shred batch" */ 26 0 : if( FD_UNLIKELY( shredder->shred_cnt == 0U ) ) 27 0 : break; 28 : 29 0 : fd_shred_t const * shred = *shredder->shreds; 30 : 31 : /* Sanity check: Type must be data shred */ 32 0 : uchar shred_type = fd_shred_type( shred->variant ); 33 0 : if( FD_UNLIKELY( shred_type!=FD_SHRED_TYPE_LEGACY_DATA 34 0 : && shred_type!=FD_SHRED_TYPE_MERKLE_DATA 35 0 : && shred_type!=FD_SHRED_TYPE_MERKLE_DATA_CHAINED 36 0 : && shred_type!=FD_SHRED_TYPE_MERKLE_DATA_CHAINED_RESIGNED ) ) 37 0 : return -FD_SHRED_EINVAL; 38 : 39 : /* Ensure entry fits next shred */ 40 0 : if( FD_UNLIKELY( shredder->bufsz < fd_shred_payload_sz(shred) ) ) 41 0 : return -FD_SHRED_ENOMEM; 42 : 43 : /* Copy shred data into entry buffer. 44 : Prior validation ensures that `data_sz` is valid. */ 45 0 : ulong payload_sz = fd_shred_payload_sz( shred ); 46 0 : fd_memcpy( shredder->buf, fd_shred_data_payload( shred ), payload_sz ); 47 : 48 : /* Seek forward dst cursor */ 49 0 : shredder->buf += payload_sz; 50 0 : shredder->bufsz -= payload_sz; 51 : 52 : /* Seek forward src cursor */ 53 0 : shredder->shreds ++; 54 0 : shredder->shred_cnt--; 55 : 56 : /* Terminate loop if shred/entry batch is complete */ 57 0 : if( FD_UNLIKELY( shred->data.flags & FD_SHRED_DATA_FLAG_SLOT_COMPLETE ) ) { 58 0 : shredder->result = FD_SHRED_ESLOT; 59 0 : break; 60 0 : } 61 0 : if( FD_UNLIKELY( shred->data.flags & FD_SHRED_DATA_FLAG_DATA_COMPLETE ) ) { 62 0 : shredder->result = FD_SHRED_EBATCH; 63 0 : break; 64 0 : } 65 0 : } 66 : 67 : /* Graceful completion */ 68 0 : return shredder->buf - orig_buf; 69 0 : }