@@ -300,19 +300,18 @@ impl Record {
300
300
}
301
301
302
302
/// Set variable length data (qname, cigar, seq, qual).
303
- /// Note: Pre-existing aux data will be invalidated
304
- /// if called on an existing record. For this
305
- /// reason, never call push_aux() before set(). `qual` is Phred-scaled
306
- /// quality values, without any offset.
303
+ /// The aux data is left unchanged.
304
+ /// `qual` is Phred-scaled quality values, without any offset.
307
305
/// NOTE: seq.len() must equal qual.len() or this method
308
306
/// will panic. If you don't have quality values use
309
307
/// `let quals = vec![ 255 as u8; seq.len()];` as a placeholder that will
310
308
/// be recognized as missing QVs by `samtools`.
311
309
pub fn set ( & mut self , qname : & [ u8 ] , cigar : Option < & CigarString > , seq : & [ u8 ] , qual : & [ u8 ] ) {
312
- self . cigar = None ;
313
-
310
+ assert ! ( qname. len( ) < 255 ) ;
314
311
assert ! ( seq. len( ) == qual. len( ) , "seq.len() must equal qual.len()" ) ;
315
312
313
+ self . cigar = None ;
314
+
316
315
let cigar_width = if let Some ( cigar_string) = cigar {
317
316
cigar_string. len ( )
318
317
} else {
@@ -321,22 +320,30 @@ impl Record {
321
320
let q_len = qname. len ( ) + 1 ;
322
321
let extranul = extranul_from_qname ( qname) ;
323
322
324
- self . inner_mut ( ) . l_data = ( q_len
325
- + extranul
326
- + cigar_width
327
- + ( ( seq . len ( ) as f32 / 2.0 ) . ceil ( ) as usize )
328
- + qual . len ( ) ) as i32 ;
329
-
330
- assert ! ( qname . len ( ) <= 256 ) ;
331
-
323
+ let orig_aux_offset = self . qname_capacity ( )
324
+ + 4 * self . cigar_len ( )
325
+ + ( self . seq_len ( ) + 1 ) / 2
326
+ + self . seq_len ( ) ;
327
+ let new_aux_offset = q_len + extranul + cigar_width + ( seq . len ( ) + 1 ) / 2 + qual . len ( ) ;
328
+ assert ! ( orig_aux_offset <= self . inner . l_data as usize ) ;
329
+ let aux_len = self . inner . l_data as usize - orig_aux_offset ;
330
+ self . inner_mut ( ) . l_data = ( new_aux_offset + aux_len ) as i32 ;
332
331
if ( self . inner ( ) . m_data as i32 ) < self . inner ( ) . l_data {
333
332
// Verbosity due to lexical borrowing
334
333
let l_data = self . inner ( ) . l_data ;
335
334
self . realloc_var_data ( l_data as usize ) ;
336
335
}
337
336
337
+ // Copy the aux data.
338
+ if aux_len > 0 && orig_aux_offset != new_aux_offset {
339
+ let data =
340
+ unsafe { slice:: from_raw_parts_mut ( self . inner . data , self . inner ( ) . m_data as usize ) } ;
341
+ data. copy_within ( orig_aux_offset..orig_aux_offset + aux_len, new_aux_offset) ;
342
+ }
343
+
338
344
let data =
339
345
unsafe { slice:: from_raw_parts_mut ( self . inner . data , self . inner ( ) . l_data as usize ) } ;
346
+
340
347
// qname
341
348
utils:: copy_memory ( qname, data) ;
342
349
for i in 0 ..=extranul {
@@ -381,8 +388,6 @@ impl Record {
381
388
}
382
389
383
390
/// Replace current qname with a new one.
384
- /// Unlike set(), this preserves all the variable length data including
385
- /// the aux.
386
391
pub fn set_qname ( & mut self , new_qname : & [ u8 ] ) {
387
392
// 251 + 1NUL is the max 32-bit aligned value that fits in u8
388
393
assert ! ( new_qname. len( ) < 252 ) ;
@@ -573,7 +578,6 @@ impl Record {
573
578
}
574
579
575
580
/// Add auxiliary data.
576
- /// push_aux() should never be called before set().
577
581
pub fn push_aux ( & mut self , tag : & [ u8 ] , value : & Aux < ' _ > ) {
578
582
let ctag = tag. as_ptr ( ) as * mut i8 ;
579
583
let ret = unsafe {
0 commit comments