Skip to content

Commit 3fa020d

Browse files
fix issue #195.
1 parent b12b363 commit 3fa020d

File tree

3 files changed

+44
-35
lines changed

3 files changed

+44
-35
lines changed

src/bam/mod.rs

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub mod record_serde;
1818

1919
use std::ffi;
2020
use std::path::Path;
21+
use std::rc::Rc;
2122
use std::slice;
2223
use std::str;
2324

@@ -93,9 +94,6 @@ pub trait Read: Sized {
9394
/// Return the header.
9495
fn header(&self) -> &HeaderView;
9596

96-
/// Return the header, mutable.
97-
fn header_mut(&mut self) -> &mut HeaderView;
98-
9997
/// Seek to the given virtual offset in the file
10098
fn seek(&mut self, offset: i64) -> Result<()> {
10199
let htsfile = unsafe { self.htsfile().as_ref() }.expect("bug: null pointer to htsFile");
@@ -158,7 +156,7 @@ fn path_as_bytes<'a, P: 'a + AsRef<Path>>(path: P, must_exist: bool) -> Result<V
158156
#[derive(Debug)]
159157
pub struct Reader {
160158
htsfile: *mut htslib::htsFile,
161-
header: HeaderView,
159+
header: Rc<HeaderView>,
162160
}
163161

164162
unsafe impl Send for Reader {}
@@ -194,7 +192,7 @@ impl Reader {
194192
let header = unsafe { htslib::sam_hdr_read(htsfile) };
195193
Ok(Reader {
196194
htsfile,
197-
header: HeaderView::new(header),
195+
header: Rc::new(HeaderView::new(header)),
198196
})
199197
}
200198

@@ -203,7 +201,13 @@ impl Reader {
203201
record: *mut htslib::bam1_t,
204202
) -> i32 {
205203
let mut _self = unsafe { (data as *mut Self).as_mut().unwrap() };
206-
unsafe { htslib::sam_read1(_self.htsfile(), _self.header_mut().inner_mut(), record) }
204+
unsafe {
205+
htslib::sam_read1(
206+
_self.htsfile(),
207+
_self.header().inner_ptr() as *mut hts_sys::sam_hdr_t,
208+
record,
209+
)
210+
}
207211
}
208212

209213
/// Iterator over the records between the (optional) virtual offsets `start` and `end`
@@ -262,15 +266,15 @@ impl Read for Reader {
262266
match unsafe {
263267
htslib::sam_read1(
264268
self.htsfile,
265-
self.header.inner_mut(),
269+
self.header().inner_ptr() as *mut hts_sys::sam_hdr_t,
266270
record.inner_ptr_mut(),
267271
)
268272
} {
269273
-1 => Ok(false),
270274
-2 => Err(Error::TruncatedRecord),
271275
-4 => Err(Error::InvalidRecord),
272276
_ => {
273-
record.set_header(self.header().clone());
277+
record.set_header(Rc::clone(&self.header));
274278

275279
Ok(true)
276280
}
@@ -303,10 +307,6 @@ impl Read for Reader {
303307
fn header(&self) -> &HeaderView {
304308
&self.header
305309
}
306-
307-
fn header_mut(&mut self) -> &mut HeaderView {
308-
&mut self.header
309-
}
310310
}
311311

312312
impl Drop for Reader {
@@ -320,7 +320,7 @@ impl Drop for Reader {
320320
#[derive(Debug)]
321321
pub struct IndexedReader {
322322
htsfile: *mut htslib::htsFile,
323-
header: HeaderView,
323+
header: Rc<HeaderView>,
324324
idx: *mut htslib::hts_idx_t,
325325
itr: Option<*mut htslib::hts_itr_t>,
326326
}
@@ -365,7 +365,7 @@ impl IndexedReader {
365365
} else {
366366
Ok(IndexedReader {
367367
htsfile,
368-
header: HeaderView::new(header),
368+
header: Rc::new(HeaderView::new(header)),
369369
idx,
370370
itr: None,
371371
})
@@ -392,7 +392,7 @@ impl IndexedReader {
392392
} else {
393393
Ok(IndexedReader {
394394
htsfile,
395-
header: HeaderView::new(header),
395+
header: Rc::new(HeaderView::new(header)),
396396
idx,
397397
itr: None,
398398
})
@@ -424,7 +424,13 @@ impl IndexedReader {
424424
}
425425
let rstr = ffi::CString::new(region).unwrap();
426426
let rptr = rstr.as_ptr();
427-
let itr = unsafe { htslib::sam_itr_querys(self.idx, self.header.inner_mut(), rptr) };
427+
let itr = unsafe {
428+
htslib::sam_itr_querys(
429+
self.idx,
430+
self.header().inner_ptr() as *mut hts_sys::sam_hdr_t,
431+
rptr,
432+
)
433+
};
428434
if itr.is_null() {
429435
self.itr = None;
430436
Err(Error::Fetch)
@@ -441,7 +447,13 @@ impl IndexedReader {
441447
let _self = unsafe { (data as *mut Self).as_mut().unwrap() };
442448
match _self.itr {
443449
Some(itr) => itr_next(_self.htsfile, itr, record), // read fetched region
444-
None => unsafe { htslib::sam_read1(_self.htsfile, _self.header.inner_mut(), record) }, // ordinary reading
450+
None => unsafe {
451+
htslib::sam_read1(
452+
_self.htsfile,
453+
_self.header().inner_ptr() as *mut hts_sys::sam_hdr_t,
454+
record,
455+
)
456+
}, // ordinary reading
445457
}
446458
}
447459

@@ -464,7 +476,7 @@ impl Read for IndexedReader {
464476
-2 => Err(Error::TruncatedRecord),
465477
-4 => Err(Error::InvalidRecord),
466478
_ => {
467-
record.set_header(self.header().clone());
479+
record.set_header(Rc::clone(&self.header));
468480

469481
Ok(true)
470482
}
@@ -500,10 +512,6 @@ impl Read for IndexedReader {
500512
fn header(&self) -> &HeaderView {
501513
&self.header
502514
}
503-
504-
fn header_mut(&mut self) -> &mut HeaderView {
505-
&mut self.header
506-
}
507515
}
508516

509517
impl Drop for IndexedReader {
@@ -539,7 +547,7 @@ impl Format {
539547
#[derive(Debug)]
540548
pub struct Writer {
541549
f: *mut htslib::htsFile,
542-
header: HeaderView,
550+
header: Rc<HeaderView>,
543551
}
544552

545553
unsafe impl Send for Writer {}
@@ -615,7 +623,7 @@ impl Writer {
615623

616624
Ok(Writer {
617625
f,
618-
header: HeaderView::new(header_record),
626+
header: Rc::new(HeaderView::new(header_record)),
619627
})
620628
}
621629

@@ -1544,7 +1552,7 @@ CCCCCCCCCCCCCCCCCCC"[..],
15441552
let sam_recs: Vec<Record> = sam
15451553
.split(|x| *x == b'\n')
15461554
.filter(|x| x.len() > 0 && x[0] != b'@')
1547-
.map(|line| Record::from_sam(rdr.header_mut(), line).unwrap())
1555+
.map(|line| Record::from_sam(rdr.header(), line).unwrap())
15481556
.collect();
15491557

15501558
for (b1, s1) in bam_recs.iter().zip(sam_recs.iter()) {

src/bam/record.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::ffi;
88
use std::fmt;
99
use std::mem::{size_of, MaybeUninit};
1010
use std::ops;
11+
use std::rc::Rc;
1112
use std::slice;
1213
use std::str;
1314
use std::str::FromStr;
@@ -48,7 +49,7 @@ pub struct Record {
4849
pub inner: htslib::bam1_t,
4950
own: bool,
5051
cigar: Option<CigarStringView>,
51-
header: Option<HeaderView>,
52+
header: Option<Rc<HeaderView>>,
5253
}
5354

5455
unsafe impl Send for Record {}
@@ -137,7 +138,7 @@ impl Record {
137138
}
138139

139140
// Create a BAM record from a line SAM text. SAM slice need not be 0-terminated.
140-
pub fn from_sam(header_view: &mut HeaderView, sam: &[u8]) -> Result<Record> {
141+
pub fn from_sam(header_view: &HeaderView, sam: &[u8]) -> Result<Record> {
141142
let mut record = Self::new();
142143

143144
let mut sam_copy = Vec::with_capacity(sam.len() + 1);
@@ -153,7 +154,7 @@ impl Record {
153154
let succ = unsafe {
154155
htslib::sam_parse1(
155156
&mut sam_string,
156-
header_view.inner_ptr_mut(),
157+
header_view.inner_ptr() as *mut htslib::bam_hdr_t,
157158
record.inner_ptr_mut(),
158159
)
159160
};
@@ -167,7 +168,7 @@ impl Record {
167168
}
168169
}
169170

170-
pub fn set_header(&mut self, header: HeaderView) {
171+
pub fn set_header(&mut self, header: Rc<HeaderView>) {
171172
self.header = Some(header);
172173
}
173174

src/bcf/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ impl Read for Reader {
123123
// Always unpack record.
124124
htslib::bcf_unpack(record.inner_mut(), htslib::BCF_UN_ALL as i32);
125125
}
126-
record.set_header(self.header.clone());
126+
record.set_header(Rc::clone(&self.header));
127127
Ok(true)
128128
}
129129
-1 => Ok(false),
@@ -145,7 +145,7 @@ impl Read for Reader {
145145

146146
/// Return empty record. Can be reused multiple times.
147147
fn empty_record(&self) -> Record {
148-
Record::new(self.header.clone())
148+
Record::new(Rc::clone(&self.header))
149149
}
150150
}
151151

@@ -263,7 +263,7 @@ impl Read for IndexedReader {
263263
);
264264
}
265265

266-
record.set_header(self.header.clone());
266+
record.set_header(Rc::clone(&self.header));
267267

268268
match self.current_region {
269269
Some((rid, _start, end)) => {
@@ -302,7 +302,7 @@ impl Read for IndexedReader {
302302
}
303303

304304
fn empty_record(&self) -> Record {
305-
Record::new(self.header.clone())
305+
Record::new(Rc::clone(&self.header))
306306
}
307307
}
308308

@@ -618,7 +618,7 @@ impl Writer {
618618
///
619619
/// This record can then be reused multiple times.
620620
pub fn empty_record(&self) -> Record {
621-
record::Record::new(self.header.clone())
621+
record::Record::new(Rc::clone(&self.header))
622622
}
623623

624624
/// Translate record to header of this writer.
@@ -630,7 +630,7 @@ impl Writer {
630630
unsafe {
631631
htslib::bcf_translate(self.header.inner, record.header().inner, record.inner);
632632
}
633-
record.set_header(self.header.clone());
633+
record.set_header(Rc::clone(&self.header));
634634
}
635635

636636
/// Subset samples of record to match header of this writer.

0 commit comments

Comments
 (0)