Skip to content

Commit d480e1b

Browse files
committed
refactor: usize to SizeType conversion is now fallible.
* New behavior reflects underlying types. BREAKING CHANGE: From<usize> is now TryFrom<usize>
1 parent 9241f9e commit d480e1b

File tree

3 files changed

+60
-14
lines changed

3 files changed

+60
-14
lines changed

src/_macros.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -676,12 +676,13 @@ macro_rules! node_table_add_row_with_metadata {
676676
M: $crate::metadata::NodeMetadata,
677677
{
678678
let md = $crate::metadata::EncodedMetadata::new(metadata)?;
679+
let mdlen = md.len()?;
679680
node_table_add_row_details!(flags,
680681
time,
681682
population,
682683
individual,
683684
md.as_ptr(),
684-
md.len().into(),
685+
mdlen.into(),
685686
$table)
686687
}
687688
};
@@ -761,7 +762,7 @@ macro_rules! edge_table_add_row_with_metadata {
761762
parent,
762763
child,
763764
md.as_ptr(),
764-
md.len().into(),
765+
md.len()?.into(),
765766
$table)
766767
}
767768
};
@@ -791,7 +792,7 @@ macro_rules! population_table_add_row_with_metadata {
791792
pub fn $name<M>(&mut $self, metadata: &M) -> Result<$crate::PopulationId, $crate::TskitError>
792793
where M: $crate::metadata::PopulationMetadata {
793794
let md = $crate::metadata::EncodedMetadata::new(metadata)?;
794-
population_table_add_row_details!(md.as_ptr(), md.len().into(), $table)
795+
population_table_add_row_details!(md.as_ptr(), md.len()?.into(), $table)
795796
}
796797
};
797798
}
@@ -865,7 +866,7 @@ macro_rules! individual_table_add_row_with_metadata {
865866
location,
866867
parents,
867868
md.as_ptr(),
868-
md.len().into(),
869+
md.len()?.into(),
869870
$table)
870871
}
871872
};
@@ -946,7 +947,7 @@ macro_rules! mutation_table_add_row_with_metadata {
946947
time,
947948
derived_state,
948949
md.as_ptr(),
949-
md.len().into(),
950+
md.len()?.into(),
950951
$table)
951952
}
952953
};
@@ -1002,7 +1003,7 @@ macro_rules! site_table_add_row_with_metadata {
10021003
let md = $crate::metadata::EncodedMetadata::new(metadata)?;
10031004
site_table_add_row_details!(position, ancestral_state,
10041005
md.as_ptr(),
1005-
md.len().into(),
1006+
md.len()?.into(),
10061007
$table)
10071008
}
10081009
};
@@ -1076,7 +1077,7 @@ macro_rules! migration_table_add_row_with_metadata {
10761077
{
10771078
let md = $crate::metadata::EncodedMetadata::new(metadata)?;
10781079
migration_table_add_row_details!(span, node, source_dest, time,
1079-
md.as_ptr(), md.len().into(), $table)
1080+
md.as_ptr(), md.len()?.into(), $table)
10801081
}
10811082
};
10821083
}

src/lib.rs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,27 @@ impl_size_type_comparisons_for_row_ids!(MigrationId);
263263
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, std::hash::Hash)]
264264
pub struct SizeType(tsk_size_t);
265265

266+
impl SizeType {
267+
/// Convenience function to convert to usize.
268+
///
269+
/// Works via [`TryFrom`].
270+
///
271+
/// # Returns
272+
///
273+
/// * `None` if the underlying value is negative.
274+
/// * `Some(usize)` otherwise.
275+
pub fn to_usize(&self) -> Option<usize> {
276+
(*self).try_into().ok()
277+
}
278+
279+
/// Convenience function to convert to usize.
280+
/// Implemented via `as`.
281+
/// Negative values with therefore wrap.
282+
pub fn as_usize(&self) -> usize {
283+
self.0 as usize
284+
}
285+
}
286+
266287
impl std::fmt::Display for SizeType {
267288
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
268289
write!(f, "{}", self.0)
@@ -297,9 +318,17 @@ impl TryFrom<SizeType> for usize {
297318
}
298319
}
299320

300-
impl From<usize> for SizeType {
301-
fn from(value: usize) -> Self {
302-
Self(value as tsk_size_t)
321+
impl TryFrom<usize> for SizeType {
322+
type Error = TskitError;
323+
324+
fn try_from(value: usize) -> Result<Self, Self::Error> {
325+
match tsk_size_t::try_from(value) {
326+
Ok(x) => Ok(Self(x)),
327+
Err(_) => Err(TskitError::RangeError(format!(
328+
"could not convert usize {} to SizeType",
329+
value
330+
))),
331+
}
303332
}
304333
}
305334

@@ -539,6 +568,22 @@ mod tests {
539568
}
540569
}
541570

571+
#[test]
572+
fn test_usize_to_size_type() {
573+
let x = usize::MAX;
574+
let s = SizeType::try_from(x).ok();
575+
576+
#[cfg(target_pointer_width = "64")]
577+
assert_eq!(s, Some(bindings::tsk_size_t::MAX.into()));
578+
579+
#[cfg(target_pointer_width = "32")]
580+
assert_eq!(s, Some((usize::MAX as bindings::tsk_size_t).into()));
581+
582+
let x = usize::MIN;
583+
let s = SizeType::try_from(x).ok();
584+
assert_eq!(s, Some(0.into()));
585+
}
586+
542587
// Testing modules
543588
mod test_fixtures;
544589
mod test_simplification;

src/metadata.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,8 @@ impl EncodedMetadata {
234234
}
235235
}
236236

237-
pub(crate) fn len(&self) -> SizeType {
238-
self.encoded.len().into()
237+
pub(crate) fn len(&self) -> Result<SizeType, crate::TskitError> {
238+
SizeType::try_from(self.encoded.len())
239239
}
240240
}
241241

@@ -365,7 +365,7 @@ mod tests {
365365
let enc = EncodedMetadata::new(&f).unwrap();
366366
let p = enc.as_ptr();
367367
let mut d = vec![];
368-
for i in 0..usize::try_from(enc.len()).unwrap() {
368+
for i in 0..usize::try_from(enc.len().unwrap()).unwrap() {
369369
d.push(unsafe { *p.add(i) as u8 });
370370
}
371371
let df = F::decode(&d).unwrap();
@@ -399,7 +399,7 @@ mod test_serde {
399399
let enc = EncodedMetadata::new(&f).unwrap();
400400
let p = enc.as_ptr();
401401
let mut d = vec![];
402-
for i in 0..usize::try_from(enc.len()).unwrap() {
402+
for i in 0..usize::try_from(enc.len().unwrap()).unwrap() {
403403
d.push(unsafe { *p.add(i) as u8 });
404404
}
405405
let df = F::decode(&d).unwrap();

0 commit comments

Comments
 (0)