@@ -1100,6 +1100,41 @@ impl AssetRef {
11001100 f ( Some ( & self ) , child) ;
11011101 }
11021102 }
1103+
1104+ /// Get an [`AssetRef`] representing a subset of this parent's children.
1105+ ///
1106+ /// # Panics
1107+ ///
1108+ /// Panics if this asset is not a parent asset or `num_units` is zero or exceeds the total
1109+ /// capacity of this asset.
1110+ pub fn make_partial_parent ( & self , num_units : u32 ) -> Self {
1111+ assert ! (
1112+ self . is_parent( ) ,
1113+ "Cannot make a partial parent from a non-parent asset"
1114+ ) ;
1115+ assert ! (
1116+ num_units > 0 ,
1117+ "Cannot make a partial parent with zero units"
1118+ ) ;
1119+
1120+ let ( max_num_units, unit_size) = match self . capacity ( ) {
1121+ AssetCapacity :: Discrete ( max_num_units, unit_size) => ( max_num_units, unit_size) ,
1122+ // We know asset capacity type is discrete as this is a parent asset
1123+ AssetCapacity :: Continuous ( _) => unreachable ! ( ) ,
1124+ } ;
1125+ match num_units. cmp ( & max_num_units) {
1126+ // Make a new Asset with fewer units
1127+ Ordering :: Less => Self :: from ( Asset {
1128+ capacity : Cell :: new ( AssetCapacity :: Discrete ( num_units, unit_size) ) ,
1129+ ..Asset :: clone ( self )
1130+ } ) ,
1131+ // Same number of units as self
1132+ Ordering :: Equal => self . clone ( ) ,
1133+ Ordering :: Greater => {
1134+ panic ! ( "Cannot make a partial parent with more units than original" )
1135+ }
1136+ }
1137+ }
11031138}
11041139
11051140impl From < Rc < Asset > > for AssetRef {
@@ -1429,6 +1464,64 @@ mod tests {
14291464 assert_eq ! ( count, 1 ) ;
14301465 }
14311466
1467+ #[ fixture]
1468+ fn parent_asset ( asset_divisible : Asset ) -> AssetRef {
1469+ let asset = AssetRef :: from ( asset_divisible) ;
1470+ let mut parent = None ;
1471+
1472+ asset. into_for_each_child ( & mut 0 , |maybe_parent, _| {
1473+ if parent. is_none ( ) {
1474+ parent = maybe_parent. cloned ( ) ;
1475+ }
1476+ } ) ;
1477+
1478+ parent. expect ( "Divisible asset should create a parent" )
1479+ }
1480+
1481+ #[ rstest]
1482+ #[ case:: subset_of_children( 2 , false ) ]
1483+ #[ case:: all_children( 3 , true ) ]
1484+ fn make_partial_parent (
1485+ parent_asset : AssetRef ,
1486+ #[ case] num_units : u32 ,
1487+ #[ case] expect_same_asset : bool ,
1488+ ) {
1489+ let parent = parent_asset;
1490+ assert ! ( parent. is_parent( ) ) ;
1491+
1492+ let partial_parent = parent. make_partial_parent ( num_units) ;
1493+
1494+ assert ! ( partial_parent. is_parent( ) ) ;
1495+ assert_eq ! (
1496+ partial_parent. capacity( ) ,
1497+ AssetCapacity :: Discrete ( num_units, Capacity ( 4.0 ) )
1498+ ) ;
1499+ assert_eq ! ( partial_parent. num_children( ) , Some ( num_units) ) ;
1500+ assert_eq ! ( partial_parent. group_id( ) , parent. group_id( ) ) ;
1501+ assert_eq ! ( partial_parent. agent_id( ) , parent. agent_id( ) ) ;
1502+ assert_eq ! ( Rc :: ptr_eq( & partial_parent. 0 , & parent. 0 ) , expect_same_asset) ;
1503+ assert_eq ! ( parent. capacity( ) , AssetCapacity :: Discrete ( 3 , Capacity ( 4.0 ) ) ) ;
1504+ }
1505+
1506+ #[ rstest]
1507+ #[ should_panic( expected = "Cannot make a partial parent from a non-parent asset" ) ]
1508+ fn make_partial_parent_panics_for_non_parent_asset ( asset_divisible : Asset ) {
1509+ let asset = AssetRef :: from ( asset_divisible) ;
1510+ asset. make_partial_parent ( 1 ) ;
1511+ }
1512+
1513+ #[ rstest]
1514+ #[ should_panic( expected = "Cannot make a partial parent with zero units" ) ]
1515+ fn make_partial_parent_panics_for_zero_units ( parent_asset : AssetRef ) {
1516+ parent_asset. make_partial_parent ( 0 ) ;
1517+ }
1518+
1519+ #[ rstest]
1520+ #[ should_panic( expected = "Cannot make a partial parent with more units than original" ) ]
1521+ fn make_partial_parent_panics_for_too_many_units ( parent_asset : AssetRef ) {
1522+ parent_asset. make_partial_parent ( 4 ) ;
1523+ }
1524+
14321525 #[ rstest]
14331526 fn asset_commission ( process : Process ) {
14341527 // Test successful commissioning of Future asset
0 commit comments