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