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( !fd_shred_is_data( shred_type ) ) ) 35 0 : return -FD_SHRED_EINVAL; 36 : 37 : /* Ensure entry fits next shred */ 38 0 : 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 0 : ulong payload_sz = fd_shred_payload_sz( shred ); 44 0 : fd_memcpy( shredder->buf, fd_shred_data_payload( shred ), payload_sz ); 45 : 46 : /* Seek forward dst cursor */ 47 0 : shredder->buf += payload_sz; 48 0 : shredder->bufsz -= payload_sz; 49 : 50 : /* Seek forward src cursor */ 51 0 : shredder->shreds ++; 52 0 : shredder->shred_cnt--; 53 : 54 : /* Terminate loop if shred/entry batch is complete */ 55 0 : if( FD_UNLIKELY( shred->data.flags & FD_SHRED_DATA_FLAG_SLOT_COMPLETE ) ) { 56 0 : shredder->result = FD_SHRED_ESLOT; 57 0 : break; 58 0 : } 59 0 : if( FD_UNLIKELY( shred->data.flags & FD_SHRED_DATA_FLAG_DATA_COMPLETE ) ) { 60 0 : shredder->result = FD_SHRED_EBATCH; 61 0 : break; 62 0 : } 63 0 : } 64 : 65 : /* Graceful completion */ 66 0 : return shredder->buf - orig_buf; 67 0 : }