{"args":{"content":"# How does smallvec::SmallVec::from_vec differ from smallvec::smallvec! macro for initialization?

from_vec converts an existing Vec into a SmallVec, potentially avoiding allocation if the data fits within the inline capacity, while smallvec! is a macro that constructs a SmallVec directly from element values with syntax similar to vec!. The key difference is input source: from_vec takes ownership of a pre-existing vector (useful when you have data already in a Vec), while smallvec! creates a SmallVec from individual elements (useful for literals and direct construction). Use from_vec when converting from Vec or when data already exists in vector form, and smallvec! for inline construction similar to how you'd use vec!.

Basic smallvec! Macro Usage

use smallvec::SmallVec;
 
fn main() {
    // smallvec! creates SmallVec from elements
    let sv: SmallVec<[i32; 4]> = smallvec::smallvec![1, 2, 3, 4];
    
    // Similar to vec! syntax
    let v = vec![1, 2, 3, 4];
    
    // smallvec! with type annotation for inline capacity
    // [i32; 4] means: inline array of i32 with capacity 4
    let sv_inline: SmallVec<[i32; 8]> = smallvec::smallvec![1, 2, 3];
    
    // Elements are constructed directly into SmallVec
    // No intermediate Vec allocation if elements fit inline
    
    println!(\"SmallVec: {:?}\", sv);
}

smallvec! constructs SmallVec directly from elements.

Basic from_vec Usage

use smallvec::SmallVec;
 
fn main() {\n    // from_vec converts existing Vec to SmallVec\n    let vec = vec![1, 2, 3, 4, 5];\n    let sv: SmallVec<[i32; 4]> = SmallVec::from_vec(vec);\n    \n    // If elements exceed inline capacity, heap is used\n    // Original Vec's heap allocation may be reused\n    \n    println!(\"SmallVec: {:?}\", sv);\n    \n    // from_vec is useful when you already have a Vec\n    fn process_data(data: Vec<i32>) -> SmallVec<[i32; 16]> {\n        SmallVec::from_vec(data)\n    }\n    \n    let result = process_data(vec![10, 20, 30]);\n    println!(\"Processed: {:?}\", result);\n}

from_vec converts an existing Vec into a SmallVec.

Inline Capacity Behavior

use smallvec::SmallVec;
 
fn main() {
n    // smallvec! with elements fitting inline capacity\n    let sv1: SmallVec<[i32; 4]> = smallvec::smallvec![1, 2, 3];\n    // Stored inline, no heap allocation\n    \n    // smallvec! with elements exceeding inline capacity\n    let sv2: SmallVec<[i32; 2]> = smallvec::smallvec![1, 2, 3, 4, 5];\n    // Elements don't fit, heap allocated\n    \n    // from_vec with elements fitting inline\n    let vec1 = vec![1, 2, 3];\n    let sv3: SmallVec<[i32; 4]> = SmallVec::from_vec(vec1);\n    // Vec's allocation freed, elements moved to inline storage\n    \n    // from_vec with elements exceeding inline\n    let vec2 = vec![1, 2, 3, 4, 5];\n    let sv4: SmallVec<[i32; 2]> = SmallVec::from_vec(vec2);\n    // Vec's heap allocation may be reused\n    \n    println!(\"All created successfully\");\n}

Both handle inline capacity, but from_vec may reuse existing heap allocation.

Empty Initialization Differences

use smallvec::SmallVec;
 
fn main() {\n    // smallvec! for empty SmallVec\n    let empty1: SmallVec<[i32; 4]> = smallvec::smallvec![];\n    \n    // from_vec requires a Vec\n    let empty2: SmallVec<[i32; 4]> = SmallVec::from_vec(Vec::new());\n    \n    // from_vec is more verbose for empty case\n    // smallvec! is cleaner for empty initialization\n    \n    // Alternative: SmallVec::new()\n    let empty3: SmallVec<[i32; 4]> = SmallVec::new();\n    \n    println!(\"Empty SmallVecs created\");\n}

smallvec![] is cleaner for empty initialization; from_vec(Vec::new()) is verbose.

Repeated Elements

use smallvec::SmallVec;
 
fn main() {\n    // smallvec! supports repeat syntax like vec!\n    let sv1: SmallVec<[i32; 10]> = smallvec::smallvec![0; 5];\n    // Creates [0, 0, 0, 0, 0]\n    \n    // from_vec would require:\n    let sv2: SmallVec<[i32; 10]> = SmallVec::from_vec(vec![0; 5]);\n    \n    // Both produce same result\n    assert_eq!(sv1, sv2);\n    \n    println!(\"Repeated elements: {:?}\", sv1);\n}

smallvec! supports vec!-like repeat syntax; from_vec requires creating Vec first.

Memory Allocation Behavior

use smallvec::SmallVec;\n\nfn main() {\n    // smallvec! directly constructs elements\n    // If elements fit inline: no allocation\n    // If too many: allocates on heap\n    \n    let sv1: SmallVec<[i32; 4]> = smallvec::smallvec![1, 2, 3];\n    // Fits inline: no heap allocation\n    \n    // from_vec: Vec already has allocation\n    // If elements fit inline: Vec allocation freed\n    // If too many: Vec's allocation may be reused\n    \n    let vec = vec![1, 2, 3];\n    let sv2: SmallVec<[i32; 4]> = SmallVec::from_vec(vec);\n    // Vec's allocation freed, elements moved inline\n    \n    let vec = vec![1, 2, 3, 4, 5, 6, 7, 8];\n    let sv3: SmallVec<[i32; 2]> = SmallVec::from_vec(vec);\n    // Elements exceed inline capacity\n    // Vec's heap allocation may be transferred to SmallVec\n    \n    println!(\"SmallVecs created\");\n}

from_vec may reuse Vec's heap allocation when elements exceed inline capacity.

Converting from Collections

use smallvec::SmallVec;
 
fn main() {\n    // from_vec is useful when you receive a Vec from elsewhere\n    fn process(input: Vec<String>) -> SmallVec<[String; 8]> {\n        SmallVec::from_vec(input)\n    }\n    \n    // from_vec from iterator (requires Vec intermediate)\n    let sv1: SmallVec<[i32; 4]> = SmallVec::from_vec(\n        (0..5).collect()\n    );\n    \n    // Alternative: SmallVec::from_iter (no Vec intermediate)\n    let sv2: SmallVec<[i32; 4]> = (0..5).collect();\n    \n    // from_iter is more efficient than from_vec for iterators\n    // But from_vec is useful when you already have a Vec\n    \n    println!(\"Converted collections\");\n}

from_vec is useful for converting existing Vec; use from_iter for iterators.

Performance Considerations

use smallvec::SmallVec;\n\nfn main() {\n    // smallvec! may be slightly faster for inline cases\n    // because elements are constructed directly\n    \n    // from_vec for inline: Vec allocation + free\n    // smallvec! for inline: direct construction\n    \n    // For heap cases:\n    // from_vec: may reuse Vec's allocation\n    // smallvec!: always allocates new\n    \n    use std::time::Instant;\n    \n    let iterations = 100_000;\n    \n    // Measure smallvec!\n    let start = Instant::now();\n    for _ in 0..iterations {\n        let _: SmallVec<[i32; 4]> = smallvec::smallvec![1, 2, 3];\n    }\n    let smallvec_time = start.elapsed();\n    \n    // Measure from_vec\n    let start = Instant::now();\n    for _ in 0..iterations {\n        let _: SmallVec<[i32; 4]> = SmallVec::from_vec(vec![1, 2, 3]);\n    }\n    let from_vec_time = start.elapsed();\n    \n    println!(\"smallvec!: {:?}\", smallvec_time);\n    println!(\"from_vec: {:?}\", from_vec_time);\n    // smallvec! is typically faster for inline cases\n    // because no Vec allocation is needed\n}

smallvec! avoids intermediate Vec allocation; from_vec includes Vec overhead.

Macro vs Function Trade-offs

use smallvec::SmallVec;\n\nfn main() {\n    // smallvec! advantages:\n    // - Concise syntax similar to vec!\n    // - Direct construction, no intermediate Vec\n    // - Compile-time element checking\n    // - Clear for literals and constants\n    \n    // from_vec advantages:\n    // - Works with existing Vec\n    // - Function call, not macro\n    // - Works with dynamic data\n    // - Can transfer heap allocation\n    \n    // Use smallvec! for literals\n    let literal: SmallVec<[&str; 4]> = smallvec::smallvec![\"a\", \"b\", \"c\"];\n    \n    // Use from_vec for dynamic data\n    let dynamic: Vec<i32> = get_data();\n    let sv: SmallVec<[i32; 8]> = SmallVec::from_vec(dynamic);\n    \n    // Use from_vec when converting\n    fn convert_small_vec(input: Vec<u8>) -> SmallVec<[u8; 32]> {\n        SmallVec::from_vec(input)\n    }\n    \n    println!(\"Created SmallVecs\");\n}\n\nfn get_data() -> Vec<i32> {\n    vec![1, 2, 3, 4, 5]\n}

Use smallvec! for literals, from_vec for existing Vec.

Growing Beyond Inline Capacity

use smallvec::SmallVec;\n\nfn main() {\n    // Both can grow beyond inline capacity\n    \n    // smallvec! starts inline, may grow to heap\n    let mut sv1: SmallVec<[i32; 2]> = smallvec::smallvec![1, 2];\n    sv1.push(3); // Now on heap\n    \n    // from_vec: if Vec is large, may already be on heap\n    let mut sv2: SmallVec<[i32; 2]> = SmallVec::from_vec(vec![1, 2, 3, 4]);\n    // Already on heap (exceeded inline capacity of 2)\n    sv2.push(5); // Still on heap, allocation may be reused\n    \n    println!(\"sv1: {:?}\", sv1);\n    println!(\"sv2: {:?}\", sv2);\n}

Both handle growing beyond inline capacity; from_vec may reuse existing allocation.

Type Inference

use smallvec::SmallVec;\n\nfn main() {\n    // smallvec! requires type annotation for inline capacity\n    let sv1: SmallVec<[i32; 4]> = smallvec::smallvec![1, 2, 3];\n    \n    // from_vec also needs type annotation or inference\n    let vec = vec![1, 2, 3];\n    let sv2: SmallVec<[i32; 4]> = SmallVec::from_vec(vec);\n    \n    // Both need explicit type for inline capacity\n    // Compiler can't infer inline capacity from usage\n    \n    // Function can provide type inference\n    fn make_smallvec() -> SmallVec<[i32; 8]> {\n        smallvec::smallvec![1, 2, 3]\n    }\n    \n    fn from_small_vec(v: Vec<i32>) -> SmallVec<[i32; 8]> {\n        SmallVec::from_vec(v)\n    }\n    \n    println!(\"Type inference works with function signatures\");\n}

Both require explicit type annotation for inline capacity.

Drain and Move Semantics

use smallvec::SmallVec;\n\nfn main() {\n    // smallvec! moves elements into SmallVec\n    let strings: SmallVec<[String; 4]> = smallvec::smallvec![\n        String::from(\"a\"),\n        String::from(\"b\"),\n    ];\n    // Elements moved directly\n    \n    // from_vec takes ownership of Vec\n    let vec = vec![String::from(\"a\"), String::from(\"b\")];\n    let sv: SmallVec<[String; 4]> = SmallVec::from_vec(vec);\n    // vec is consumed, its elements moved\n    \n    // Both result in owned elements in SmallVec\n    // Neither clones elements\n    \n    println!(\"SmallVecs own their elements\");\n}

Both take ownership of elements; no cloning involved.

Use with Generic Types

use smallvec::SmallVec;\n\nfn main() {\n    // smallvec! works with generic types\n    let sv1: SmallVec<[Option<i32>; 4]> = smallvec::smallvec![Some(1), None, Some(3)];\n    \n    // from_vec works with any Vec<T>\n    let vec: Vec<Option<i32>> = vec![Some(1), None, Some(3)];\n    let sv2: SmallVec<[Option<i32>; 4]> = SmallVec::from_vec(vec);\n    \n    // Both handle complex types equally\n    \n    // Nested SmallVecs\n    type Inner = SmallVec<[i32; 4]>;\n    let nested: SmallVec<[Inner; 2]> = smallvec::smallvec![\n        smallvec::smallvec![1, 2],\n        smallvec::smallvec![3, 4],\n    ];\n    \n    println!(\"Generic types work with both\");\n}

Both support any element type; use whichever is convenient.

Comparison Summary

rust\nuse smallvec::SmallVec;\n\nfn main() {\n // smallvec! macro\n // - Syntax: smallvec![elem1, elem2, ...]\n // - Creates SmallVec directly from elements\n // - Supports repeat syntax: smallvec![value; count]\n // - No intermediate Vec allocation for inline\n // - Good for: literals, constants, inline construction\n // - Macro invocation, not function call\n \n // SmallVec::from_vec\n // - Syntax: SmallVec::from_vec(vec)\n // - Converts existing Vec to SmallVec\n // - Takes ownership of Vec\n // - May reuse Vec's heap allocation\n // - Good for: converting from Vec, dynamic data\n // - Function call\n \n // Alternative: SmallVec::from_iter\n // - Syntax: iter.collect() or SmallVec::from_iter(iter)\n // - No intermediate Vec\n // - Good for: converting from iterators\n \n let from_macro: SmallVec<[i32; 4]> = smallvec::smallvec![1, 2, 3];\n let from_vec: SmallVec<[i32; 4]> = SmallVec::from_vec(vec![1, 2, 3]);\n let from_iter: SmallVec<[i32; 4]> = (1..=3).collect();\n \n assert_eq!(from_macro, from_vec);\n assert_eq!(from_macro, from_iter);\n}\n\n\nChoose based on data source: literal elements vs. existing Vec vs. iterator.

Synthesis\n\nsmallvec! characteristics:\n- Macro invocation with vec!-like syntax\n- Constructs SmallVec directly from elements\n- Supports repeat syntax: smallvec![value; count]\n- No intermediate allocation for inline cases\n- Clean syntax for literals and constants\n- Compile-time element validation\n\nfrom_vec characteristics:\n- Function that converts Vec<T> to SmallVec<T, N>\n- Takes ownership of existing Vec\n- May reuse Vec's heap allocation for large data\n- Useful when data already in Vec\n- Works with dynamically constructed data\n- No macro needed\n\nAllocation behavior:\n- smallvec!: Constructs elements directly; if they fit inline, no allocation\n- from_vec: If elements fit inline, Vec allocation freed; if too many, Vec allocation may be reused\n- For inline-fitting data, smallvec! avoids allocation entirely\n- For large data, from_vec may avoid reallocation by reusing Vec's buffer\n\nUse smallvec! when:\n- Creating SmallVec from literal elements\n- Inline construction with known values\n- Writing constants or static values\n- Clean, vec!-like syntax desired\n- Elements are constructed inline\n\nUse from_vec when:\n- Converting existing Vec to SmallVec\n- Data comes from a function returning Vec\n- Dynamic construction completed in Vec\n- Want to potentially reuse heap allocation\n- Avoiding macro invocation\n\nAlternatives:\n- SmallVec::new(): Empty SmallVec\n- SmallVec::from_iter(): From iterator, no Vec intermediate\n- SmallVec::with_capacity(): Pre-allocate capacity\n\nKey insight: The choice between smallvec! and from_vec depends on where your data originates. If you're constructing a SmallVec from scratch with known elements, smallvec! is more ergonomic and potentially more efficient—it constructs elements directly into the SmallVec without an intermediate Vec. If you already have a Vec (perhaps from another function or from collecting an iterator), from_vec converts it efficiently and may reuse the existing heap allocation when the data exceeds inline capacity. For iterators, prefer SmallVec::from_iter() or .collect() over from_vec to avoid the intermediate Vec entirely. The smallvec! macro's repeat syntax (smallvec![value; count]) provides additional convenience for initializing with repeated values, mirroring vec! behavior.","path":"/articles/287_smallvec_from_vec_vs_macro.md"},"tool_call":"file.create"}