Skip to main content

SemanticRequirements

Struct SemanticRequirements 

Source
pub struct SemanticRequirements {
    pub min_regions: HashMap<String, usize>,
    pub max_regions: HashMap<String, usize>,
    pub required_connections: Vec<(String, String)>,
    pub min_walkable_area: Option<usize>,
    pub required_markers: HashMap<MarkerType, usize>,
}
Expand description

Requirements for semantic-driven generation

Fields§

§min_regions: HashMap<String, usize>

Minimum number of regions of each type

§max_regions: HashMap<String, usize>

Maximum number of regions of each type

§required_connections: Vec<(String, String)>

Required connectivity between region types

§min_walkable_area: Option<usize>

Minimum total walkable area

§required_markers: HashMap<MarkerType, usize>

Required marker types and their minimum counts

Implementations§

Source§

impl SemanticRequirements

Source

pub fn none() -> Self

Create requirements with no constraints

Examples found in repository?
examples/requirements_demo.rs (line 7)
3fn main() {
4    println!("=== Generate with Requirements Demo ===\n");
5
6    // Create simple requirements that match BSP output
7    let mut requirements = SemanticRequirements::none();
8    requirements.min_regions.insert("Hall".to_string(), 1); // BSP produces "Hall" regions
9    requirements
10        .required_markers
11        .insert(MarkerType::Custom("PlayerStart".to_string()), 1); // BSP produces "PlayerStart"
12
13    println!("Requirements:");
14    println!("  - Minimum 1 Hall region");
15    println!("  - At least 1 PlayerStart marker");
16    println!();
17
18    match generate_with_requirements("bsp", 40, 30, requirements, Some(10), 12345) {
19        Ok((grid, semantic)) => {
20            println!("✅ Successfully generated map meeting requirements!");
21            println!("  Grid size: {}x{}", grid.width(), grid.height());
22            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
23            println!("  Total regions: {}", semantic.regions.len());
24
25            // Count Hall regions
26            let hall_count = semantic.regions.iter().filter(|r| r.kind == "Hall").count();
27            println!("  Hall regions: {}", hall_count);
28
29            // Count PlayerStart markers
30            let start_count = semantic
31                .markers
32                .iter()
33                .filter(|m| m.tag() == "PlayerStart")
34                .count();
35            println!("  PlayerStart markers: {}", start_count);
36
37            println!("\nFirst few regions:");
38            for (i, region) in semantic.regions.iter().take(3).enumerate() {
39                println!("  {}: {} ({} cells)", i + 1, region.kind, region.area());
40            }
41        }
42        Err(msg) => {
43            println!("❌ Failed to generate: {}", msg);
44        }
45    }
46}
More examples
Hide additional examples
examples/requirement_generation.rs (line 22)
3fn main() {
4    println!("=== Requirement-Driven Generation Demo ===\n");
5
6    // Demo 1: Basic dungeon requirements
7    println!("1. Basic Dungeon Requirements:");
8    let basic_req = SemanticRequirements::basic_dungeon();
9
10    match generate_with_requirements("bsp", 40, 30, basic_req, Some(5), 12345) {
11        Ok((grid, semantic)) => {
12            println!("  ✅ Generated valid dungeon!");
13            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
14            println!("  Regions: {}", semantic.regions.len());
15            println!("  Markers: {}", semantic.markers.len());
16        }
17        Err(msg) => println!("  ❌ Failed: {}", msg),
18    }
19
20    // Demo 2: Custom requirements
21    println!("\n2. Custom Cave Requirements:");
22    let mut cave_req = SemanticRequirements::none();
23    cave_req.min_regions.insert("cavern".to_string(), 2);
24    cave_req.min_walkable_area = Some(200);
25    cave_req
26        .required_markers
27        .insert(MarkerType::Custom("entrance".to_string()), 1);
28    cave_req
29        .required_markers
30        .insert(MarkerType::Custom("treasure".to_string()), 1);
31
32    match generate_with_requirements("cellular", 50, 40, cave_req, Some(10), 54321) {
33        Ok((grid, semantic)) => {
34            println!("  ✅ Generated valid cave system!");
35            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
36            println!("  Regions: {}", semantic.regions.len());
37
38            // Show region types
39            let mut region_types = std::collections::HashMap::new();
40            for region in &semantic.regions {
41                *region_types.entry(&region.kind).or_insert(0) += 1;
42            }
43            for (kind, count) in region_types {
44                println!("    {}: {}", kind, count);
45            }
46        }
47        Err(msg) => println!("  ❌ Failed: {}", msg),
48    }
49
50    // Demo 3: Strict requirements (likely to fail)
51    println!("\n3. Strict Requirements (demonstration of failure):");
52    let mut strict_req = SemanticRequirements::none();
53    strict_req.min_regions.insert("room".to_string(), 10); // Very strict
54    strict_req
55        .required_markers
56        .insert(MarkerType::QuestObjective { priority: 1 }, 5);
57    strict_req.min_walkable_area = Some(800);
58
59    match generate_with_requirements("bsp", 30, 20, strict_req, Some(3), 98765) {
60        Ok((grid, _semantic)) => {
61            println!("  ✅ Unexpectedly succeeded!");
62            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
63        }
64        Err(msg) => println!("  ❌ Expected failure: {}", msg),
65    }
66}
examples/complete_workflow.rs (line 103)
3fn main() {
4    println!("=== Complete Phase 1 & 2 Feature Demo ===\n");
5
6    // Demo: Complete workflow using all new features
7    println!("🏰 Generating Advanced Multi-Feature Dungeon\n");
8
9    // Step 1: Use pipeline template with custom parameters
10    println!("1. Pipeline Template Generation:");
11    let library = TemplateLibrary::new();
12    let template = library.get_template("simple_dungeon").unwrap();
13
14    let mut custom_params = std::collections::HashMap::new();
15    custom_params.insert("seed".to_string(), "12345".to_string());
16
17    let pipeline = template.instantiate(Some(custom_params));
18
19    let mut grid = Grid::new(40, 30);
20    let mut context = PipelineContext::new();
21    let mut rng = Rng::new(12345);
22
23    let result = pipeline.execute(&mut grid, &mut context, &mut rng);
24    println!(
25        "   Template execution: {}",
26        if result.success {
27            "✅ Success"
28        } else {
29            "❌ Failed"
30        }
31    );
32    println!("   Floor tiles: {}", grid.count(|t| t.is_floor()));
33
34    // Step 2: Extract semantic information
35    println!("\n2. Semantic Analysis:");
36    let extractor = SemanticExtractor::for_rooms();
37    let mut semantic = extractor.extract(&grid, &mut rng);
38
39    println!("   Regions found: {}", semantic.regions.len());
40    println!("   Original markers: {}", semantic.markers.len());
41
42    // Step 3: Add hierarchical markers based on regions
43    println!("\n3. Hierarchical Marker Placement:");
44    let mut quest_count = 0;
45    let mut loot_count = 0;
46    let mut encounter_count = 0;
47
48    for (i, region) in semantic.regions.iter().enumerate() {
49        if !region.cells.is_empty() {
50            let (x, y) = region.cells[region.cells.len() / 2]; // Middle of region
51
52            match i % 3 {
53                0 => {
54                    // Quest area
55                    semantic.markers.push(Marker::new(
56                        x,
57                        y,
58                        MarkerType::QuestObjective {
59                            priority: (i % 3 + 1) as u8,
60                        },
61                    ));
62                    quest_count += 1;
63                }
64                1 => {
65                    // Loot area
66                    semantic.markers.push(Marker::new(
67                        x,
68                        y,
69                        MarkerType::LootTier {
70                            tier: (i % 3 + 1) as u8,
71                        },
72                    ));
73                    loot_count += 1;
74                }
75                2 => {
76                    // Encounter area
77                    if i == 2 {
78                        semantic
79                            .markers
80                            .push(Marker::new(x, y, MarkerType::BossRoom));
81                    } else {
82                        semantic.markers.push(Marker::new(
83                            x,
84                            y,
85                            MarkerType::EncounterZone {
86                                difficulty: (i % 5 + 1) as u8,
87                            },
88                        ));
89                    }
90                    encounter_count += 1;
91                }
92                _ => {}
93            }
94        }
95    }
96
97    println!("   Added {} quest markers", quest_count);
98    println!("   Added {} loot markers", loot_count);
99    println!("   Added {} encounter markers", encounter_count);
100
101    // Step 4: Validate with requirements
102    println!("\n4. Requirement Validation:");
103    let mut requirements = SemanticRequirements::none();
104    requirements.min_regions.insert("Hall".to_string(), 1);
105    requirements
106        .required_markers
107        .insert(MarkerType::Custom("PlayerStart".to_string()), 1);
108
109    let validation_result = requirements.validate(&semantic);
110    println!(
111        "   Requirements met: {}",
112        if validation_result {
113            "✅ Yes"
114        } else {
115            "❌ No"
116        }
117    );
118
119    // Step 5: Marker constraints analysis
120    println!("\n5. Marker Constraint Analysis:");
121    let quest_constraints = MarkerConstraints::quest_objective();
122    let loot_constraints = MarkerConstraints::loot();
123
124    println!("   Quest marker constraints:");
125    println!(
126        "     Min distance (same type): {:?}",
127        quest_constraints.min_distance_same
128    );
129    println!(
130        "     Excluded types: {} types",
131        quest_constraints.exclude_types.len()
132    );
133
134    println!("   Loot marker constraints:");
135    println!(
136        "     Min distance (same type): {:?}",
137        loot_constraints.min_distance_same
138    );
139    println!(
140        "     Min distance (any): {:?}",
141        loot_constraints.min_distance_any
142    );
143
144    // Step 6: Multi-floor connectivity simulation
145    println!("\n6. Multi-Floor Connectivity:");
146
147    // Create a second floor based on the first
148    let mut floor2 = Grid::new(40, 30);
149    // Copy some areas from floor 1 to create overlapping regions
150    for y in 5..25 {
151        for x in 5..35 {
152            if grid.get(x, y).is_some_and(|t| t.is_floor()) && rng.random() < 0.6 {
153                floor2.set(x, y, terrain_forge::Tile::Floor);
154            }
155        }
156    }
157
158    let floors = vec![grid.clone(), floor2];
159    let mut connectivity = VerticalConnectivity::new();
160
161    connectivity.analyze_stair_candidates(&floors, 2);
162    connectivity.place_stairs(3);
163
164    println!("   Floor 1 tiles: {}", floors[0].count(|t| t.is_floor()));
165    println!("   Floor 2 tiles: {}", floors[1].count(|t| t.is_floor()));
166    println!(
167        "   Stair candidates: {}",
168        connectivity.stair_candidates.len()
169    );
170    println!("   Stairs placed: {}", connectivity.stairs.len());
171
172    // Step 7: Final summary
173    println!("\n🎯 Generation Summary:");
174    println!("   Grid size: {}x{}", grid.width(), grid.height());
175    println!("   Total floor area: {}", grid.count(|t| t.is_floor()));
176    println!(
177        "   Density: {:.1}%",
178        (grid.count(|t| t.is_floor()) as f32 / (grid.width() * grid.height()) as f32) * 100.0
179    );
180    println!("   Regions: {}", semantic.regions.len());
181    println!("   Total markers: {}", semantic.markers.len());
182
183    // Group markers by category
184    let mut categories = std::collections::HashMap::new();
185    for marker in &semantic.markers {
186        *categories.entry(marker.marker_type.category()).or_insert(0) += 1;
187    }
188
189    println!("   Marker distribution:");
190    for (category, count) in categories {
191        println!("     {}: {}", category, count);
192    }
193
194    println!(
195        "   Pipeline steps executed: {}",
196        context.execution_history().len()
197    );
198    println!("   Multi-floor stairs: {}", connectivity.stairs.len());
199
200    println!("\n✨ Advanced dungeon generation complete!");
201}
Source

pub fn basic_dungeon() -> Self

Create basic dungeon requirements

Examples found in repository?
examples/phase1_demo.rs (line 79)
76fn demo_generate_with_requirements() {
77    println!("📋 Demo 2: Generate with Requirements");
78
79    let mut requirements = SemanticRequirements::basic_dungeon();
80    requirements.min_regions.insert("room".to_string(), 4);
81    requirements
82        .required_markers
83        .insert(MarkerType::LootTier { tier: 1 }, 2);
84
85    match terrain_forge::generate_with_requirements("bsp", 60, 40, requirements, Some(5), 54321) {
86        Ok((grid, semantic)) => {
87            println!("  ✅ Generated valid dungeon!");
88            println!("  Regions: {}", semantic.regions.len());
89            println!("  Markers: {}", semantic.markers.len());
90            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
91        }
92        Err(msg) => println!("  ❌ Failed: {}", msg),
93    }
94    println!();
95}
More examples
Hide additional examples
examples/requirement_generation.rs (line 8)
3fn main() {
4    println!("=== Requirement-Driven Generation Demo ===\n");
5
6    // Demo 1: Basic dungeon requirements
7    println!("1. Basic Dungeon Requirements:");
8    let basic_req = SemanticRequirements::basic_dungeon();
9
10    match generate_with_requirements("bsp", 40, 30, basic_req, Some(5), 12345) {
11        Ok((grid, semantic)) => {
12            println!("  ✅ Generated valid dungeon!");
13            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
14            println!("  Regions: {}", semantic.regions.len());
15            println!("  Markers: {}", semantic.markers.len());
16        }
17        Err(msg) => println!("  ❌ Failed: {}", msg),
18    }
19
20    // Demo 2: Custom requirements
21    println!("\n2. Custom Cave Requirements:");
22    let mut cave_req = SemanticRequirements::none();
23    cave_req.min_regions.insert("cavern".to_string(), 2);
24    cave_req.min_walkable_area = Some(200);
25    cave_req
26        .required_markers
27        .insert(MarkerType::Custom("entrance".to_string()), 1);
28    cave_req
29        .required_markers
30        .insert(MarkerType::Custom("treasure".to_string()), 1);
31
32    match generate_with_requirements("cellular", 50, 40, cave_req, Some(10), 54321) {
33        Ok((grid, semantic)) => {
34            println!("  ✅ Generated valid cave system!");
35            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
36            println!("  Regions: {}", semantic.regions.len());
37
38            // Show region types
39            let mut region_types = std::collections::HashMap::new();
40            for region in &semantic.regions {
41                *region_types.entry(&region.kind).or_insert(0) += 1;
42            }
43            for (kind, count) in region_types {
44                println!("    {}: {}", kind, count);
45            }
46        }
47        Err(msg) => println!("  ❌ Failed: {}", msg),
48    }
49
50    // Demo 3: Strict requirements (likely to fail)
51    println!("\n3. Strict Requirements (demonstration of failure):");
52    let mut strict_req = SemanticRequirements::none();
53    strict_req.min_regions.insert("room".to_string(), 10); // Very strict
54    strict_req
55        .required_markers
56        .insert(MarkerType::QuestObjective { priority: 1 }, 5);
57    strict_req.min_walkable_area = Some(800);
58
59    match generate_with_requirements("bsp", 30, 20, strict_req, Some(3), 98765) {
60        Ok((grid, _semantic)) => {
61            println!("  ✅ Unexpectedly succeeded!");
62            println!("  Floor tiles: {}", grid.count(|t| t.is_floor()));
63        }
64        Err(msg) => println!("  ❌ Expected failure: {}", msg),
65    }
66}
Source

pub fn validate(&self, layers: &SemanticLayers) -> bool

Validate if semantic layers meet these requirements

Examples found in repository?
examples/complete_workflow.rs (line 109)
3fn main() {
4    println!("=== Complete Phase 1 & 2 Feature Demo ===\n");
5
6    // Demo: Complete workflow using all new features
7    println!("🏰 Generating Advanced Multi-Feature Dungeon\n");
8
9    // Step 1: Use pipeline template with custom parameters
10    println!("1. Pipeline Template Generation:");
11    let library = TemplateLibrary::new();
12    let template = library.get_template("simple_dungeon").unwrap();
13
14    let mut custom_params = std::collections::HashMap::new();
15    custom_params.insert("seed".to_string(), "12345".to_string());
16
17    let pipeline = template.instantiate(Some(custom_params));
18
19    let mut grid = Grid::new(40, 30);
20    let mut context = PipelineContext::new();
21    let mut rng = Rng::new(12345);
22
23    let result = pipeline.execute(&mut grid, &mut context, &mut rng);
24    println!(
25        "   Template execution: {}",
26        if result.success {
27            "✅ Success"
28        } else {
29            "❌ Failed"
30        }
31    );
32    println!("   Floor tiles: {}", grid.count(|t| t.is_floor()));
33
34    // Step 2: Extract semantic information
35    println!("\n2. Semantic Analysis:");
36    let extractor = SemanticExtractor::for_rooms();
37    let mut semantic = extractor.extract(&grid, &mut rng);
38
39    println!("   Regions found: {}", semantic.regions.len());
40    println!("   Original markers: {}", semantic.markers.len());
41
42    // Step 3: Add hierarchical markers based on regions
43    println!("\n3. Hierarchical Marker Placement:");
44    let mut quest_count = 0;
45    let mut loot_count = 0;
46    let mut encounter_count = 0;
47
48    for (i, region) in semantic.regions.iter().enumerate() {
49        if !region.cells.is_empty() {
50            let (x, y) = region.cells[region.cells.len() / 2]; // Middle of region
51
52            match i % 3 {
53                0 => {
54                    // Quest area
55                    semantic.markers.push(Marker::new(
56                        x,
57                        y,
58                        MarkerType::QuestObjective {
59                            priority: (i % 3 + 1) as u8,
60                        },
61                    ));
62                    quest_count += 1;
63                }
64                1 => {
65                    // Loot area
66                    semantic.markers.push(Marker::new(
67                        x,
68                        y,
69                        MarkerType::LootTier {
70                            tier: (i % 3 + 1) as u8,
71                        },
72                    ));
73                    loot_count += 1;
74                }
75                2 => {
76                    // Encounter area
77                    if i == 2 {
78                        semantic
79                            .markers
80                            .push(Marker::new(x, y, MarkerType::BossRoom));
81                    } else {
82                        semantic.markers.push(Marker::new(
83                            x,
84                            y,
85                            MarkerType::EncounterZone {
86                                difficulty: (i % 5 + 1) as u8,
87                            },
88                        ));
89                    }
90                    encounter_count += 1;
91                }
92                _ => {}
93            }
94        }
95    }
96
97    println!("   Added {} quest markers", quest_count);
98    println!("   Added {} loot markers", loot_count);
99    println!("   Added {} encounter markers", encounter_count);
100
101    // Step 4: Validate with requirements
102    println!("\n4. Requirement Validation:");
103    let mut requirements = SemanticRequirements::none();
104    requirements.min_regions.insert("Hall".to_string(), 1);
105    requirements
106        .required_markers
107        .insert(MarkerType::Custom("PlayerStart".to_string()), 1);
108
109    let validation_result = requirements.validate(&semantic);
110    println!(
111        "   Requirements met: {}",
112        if validation_result {
113            "✅ Yes"
114        } else {
115            "❌ No"
116        }
117    );
118
119    // Step 5: Marker constraints analysis
120    println!("\n5. Marker Constraint Analysis:");
121    let quest_constraints = MarkerConstraints::quest_objective();
122    let loot_constraints = MarkerConstraints::loot();
123
124    println!("   Quest marker constraints:");
125    println!(
126        "     Min distance (same type): {:?}",
127        quest_constraints.min_distance_same
128    );
129    println!(
130        "     Excluded types: {} types",
131        quest_constraints.exclude_types.len()
132    );
133
134    println!("   Loot marker constraints:");
135    println!(
136        "     Min distance (same type): {:?}",
137        loot_constraints.min_distance_same
138    );
139    println!(
140        "     Min distance (any): {:?}",
141        loot_constraints.min_distance_any
142    );
143
144    // Step 6: Multi-floor connectivity simulation
145    println!("\n6. Multi-Floor Connectivity:");
146
147    // Create a second floor based on the first
148    let mut floor2 = Grid::new(40, 30);
149    // Copy some areas from floor 1 to create overlapping regions
150    for y in 5..25 {
151        for x in 5..35 {
152            if grid.get(x, y).is_some_and(|t| t.is_floor()) && rng.random() < 0.6 {
153                floor2.set(x, y, terrain_forge::Tile::Floor);
154            }
155        }
156    }
157
158    let floors = vec![grid.clone(), floor2];
159    let mut connectivity = VerticalConnectivity::new();
160
161    connectivity.analyze_stair_candidates(&floors, 2);
162    connectivity.place_stairs(3);
163
164    println!("   Floor 1 tiles: {}", floors[0].count(|t| t.is_floor()));
165    println!("   Floor 2 tiles: {}", floors[1].count(|t| t.is_floor()));
166    println!(
167        "   Stair candidates: {}",
168        connectivity.stair_candidates.len()
169    );
170    println!("   Stairs placed: {}", connectivity.stairs.len());
171
172    // Step 7: Final summary
173    println!("\n🎯 Generation Summary:");
174    println!("   Grid size: {}x{}", grid.width(), grid.height());
175    println!("   Total floor area: {}", grid.count(|t| t.is_floor()));
176    println!(
177        "   Density: {:.1}%",
178        (grid.count(|t| t.is_floor()) as f32 / (grid.width() * grid.height()) as f32) * 100.0
179    );
180    println!("   Regions: {}", semantic.regions.len());
181    println!("   Total markers: {}", semantic.markers.len());
182
183    // Group markers by category
184    let mut categories = std::collections::HashMap::new();
185    for marker in &semantic.markers {
186        *categories.entry(marker.marker_type.category()).or_insert(0) += 1;
187    }
188
189    println!("   Marker distribution:");
190    for (category, count) in categories {
191        println!("     {}: {}", category, count);
192    }
193
194    println!(
195        "   Pipeline steps executed: {}",
196        context.execution_history().len()
197    );
198    println!("   Multi-floor stairs: {}", connectivity.stairs.len());
199
200    println!("\n✨ Advanced dungeon generation complete!");
201}

Trait Implementations§

Source§

impl Clone for SemanticRequirements

Source§

fn clone(&self) -> SemanticRequirements

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SemanticRequirements

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V