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