• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mattwparas / steel / 17772690385

16 Sep 2025 04:36PM UTC coverage: 43.331% (+0.04%) from 43.289%
17772690385

Pull #519

github

web-flow
Merge 98d4fd22c into 3c10433b9
Pull Request #519: fix a bunch more clippy lints

56 of 123 new or added lines in 30 files covered. (45.53%)

8 existing lines in 3 files now uncovered.

12416 of 28654 relevant lines covered (43.33%)

2985398.75 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

56.48
/crates/steel-core/src/primitives/hashmaps.rs
1
use crate::rvals::SteelHashMap;
2
use crate::stop;
3
use crate::values::HashMap;
4
use crate::{core::utils::declare_const_ref_functions, gc::Gc};
5
use crate::{
6
    rvals::{Result, SteelVal},
7
    steel_vm::builtin::BuiltInModule,
8
};
9

10
use crate::primitives::vectors::vec_construct_iter_normal;
11

12
use steel_derive::function;
13

14
declare_const_ref_functions!(
15
    HM_CONSTRUCT => hm_construct,
16
    HM_GET => steel_hash_ref,
17
    // HM_EMPTY => hm_empty,
18
);
19

20
pub const HM_INSERT: SteelVal = SteelVal::MutFunc(steel_hash_insert);
21

22
pub(crate) fn hashmap_module() -> BuiltInModule {
4✔
23
    let mut module = BuiltInModule::new("steel/hash".to_string());
16✔
24
    module
64✔
25
        .register_native_fn_definition(HM_CONSTRUCT_DEFINITION)
60✔
26
        .register_value("%keyword-hash", SteelVal::FuncV(hm_construct_keywords))
60✔
27
        .register_native_fn_definition(HASH_INSERT_DEFINITION)
52✔
28
        .register_native_fn_definition(HASH_REF_DEFINITION)
48✔
29
        .register_value("hash-get", SteelVal::FuncV(steel_hash_ref))
48✔
30
        .register_native_fn_definition(HASH_TRY_GET_DEFINITION)
40✔
31
        .register_native_fn_definition(HASH_LENGTH_DEFINITION)
36✔
32
        .register_native_fn_definition(HASH_CONTAINS_DEFINITION)
32✔
33
        .register_native_fn_definition(KEYS_TO_LIST_DEFINITION)
28✔
34
        .register_native_fn_definition(KEYS_TO_VECTOR_DEFINITION)
24✔
35
        .register_native_fn_definition(VALUES_TO_LIST_DEFINITION)
20✔
36
        .register_native_fn_definition(VALUES_TO_VECTOR_DEFINITION)
16✔
37
        .register_native_fn_definition(CLEAR_DEFINITION)
12✔
38
        .register_native_fn_definition(HM_EMPTY_DEFINITION)
8✔
39
        .register_native_fn_definition(HM_UNION_DEFINITION)
4✔
40
        .register_native_fn_definition(HASH_REMOVE_DEFINITION);
8✔
41
    module
4✔
42
}
43

44
/// Creates an immutable hash table with each given `key` mapped to the following `val`.
45
/// Each key must have a val, so the total number of arguments must be even.
46
///
47
///
48
/// (hash key val ...) -> hash?
49
///
50
/// key : hashable?
51
/// val : any/c
52
///
53
/// Note: the keys must be hashable.
54
///
55
/// # Examples
56
/// ```scheme
57
/// > (hash 'a 10 'b 20)",
58
///   r#"=> #<hashmap {
59
///        'a: 10,
60
///        'b: 20,
61
///    }>"#,
62
/// ```
63
#[steel_derive::native(name = "hash", arity = "AtLeast(0)")]
64
pub fn hm_construct(args: &[SteelVal]) -> Result<SteelVal> {
107,089✔
65
    let mut hm = HashMap::new();
214,178✔
66

67
    let mut arg_iter = args.iter().cloned();
428,356✔
68

69
    loop {
70
        match (arg_iter.next(), arg_iter.next()) {
996,984✔
71
            (Some(key), Some(value)) => {
284,314✔
72
                if key.is_hashable() {
426,471✔
73
                    hm.insert(key, value);
142,157✔
74
                } else {
75
                    stop!(TypeMismatch => "hash key not hashable!: {}", key);
×
76
                }
77
            }
78
            (None, None) => break,
107,089✔
79
            _ => {
80
                stop!(ArityMismatch => "hash map must have a value for every key!");
×
81
            }
82
        }
83
    }
84

85
    Ok(SteelVal::HashMapV(Gc::new(hm).into()))
86
}
87

88
pub fn hm_construct_keywords(args: &[SteelVal]) -> Result<SteelVal> {
×
89
    let mut hm = HashMap::new();
×
90

91
    let mut arg_iter = args.iter().cloned();
×
92

93
    loop {
94
        match (arg_iter.next(), arg_iter.next()) {
×
95
            (Some(key), Some(value)) => {
×
96
                if key.is_hashable() {
×
97
                    hm.insert(key, value);
×
98
                } else {
99
                    stop!(TypeMismatch => "hash key not hashable!: {}", key);
×
100
                }
101
            }
102
            (None, None) => break,
×
103
            _ => {
104
                stop!(ArityMismatch => "Missing keyword argument!");
×
105
            }
106
        }
107
    }
108

109
    Ok(SteelVal::HashMapV(Gc::new(hm).into()))
110
}
111

112
/// Returns a new hashmap with the given key removed. Performs a functional
113
/// update, so the old hash map is still available with the original key value pair.
114
///
115
/// (hash-remove map key) -> hash?
116
///
117
/// * map : hash?
118
/// * key : any/c
119
///
120
/// # Examples
121
/// ```scheme
122
/// > (hash-remove (hash 'a 10 'b 20) 'a)
123
///
124
/// => '#hash(('b . 20))
125
/// ```
126
#[function(name = "hash-remove")]
127
pub fn hash_remove(map: &mut SteelVal, key: SteelVal) -> Result<SteelVal> {
×
128
    if key.is_hashable() {
×
129
        if let SteelVal::HashMapV(SteelHashMap(ref mut m)) = map {
×
130
            match Gc::get_mut(m) {
131
                Some(m) => {
×
132
                    m.remove(&key);
×
133
                    Ok(std::mem::replace(map, SteelVal::Void))
×
134
                }
135
                None => {
136
                    let mut m = m.unwrap();
×
137
                    m.remove(&key);
138

139
                    Ok(SteelVal::HashMapV(Gc::new(m).into()))
140
                }
141
            }
142
        } else {
143
            stop!(TypeMismatch => "hash-insert expects a hash map, found: {:?}", map);
×
144
        }
145
    } else {
146
        stop!(TypeMismatch => "hash key not hashable: {:?}", key)
×
147
    }
148
}
149

150
/// Returns a new hashmap with the additional key value pair added. Performs a functional update,
151
/// so the old hash map is still accessible.
152
///
153
/// (hash-insert map key val) -> hash?
154
///
155
/// * map : hash?
156
/// * key : any/c
157
/// * val : any/c
158
///
159
/// # Examples
160
/// ```scheme
161
/// > (hash-insert (hash 'a 10 'b 20) 'c 30)
162
///
163
/// => #<hashmap {
164
///         'a: 10,
165
///         'b: 20,
166
///         'c: 30
167
///     }>
168
/// ```
169
#[function(name = "hash-insert")]
170
pub fn hash_insert(
1,414✔
171
    map: &mut SteelVal,
172
    key: &mut SteelVal,
173
    value: &mut SteelVal,
174
) -> Result<SteelVal> {
175
    if key.is_hashable() {
2,828✔
176
        let key = std::mem::take(key);
4,242✔
177
        let value = std::mem::take(value);
4,242✔
178
        if let SteelVal::HashMapV(SteelHashMap(ref mut m)) = map {
2,828✔
179
            match Gc::get_mut(m) {
180
                Some(m) => {
1,359✔
181
                    m.insert(key, value);
5,436✔
182
                    Ok(std::mem::replace(map, SteelVal::Void))
2,718✔
183
                }
184
                None => Ok(SteelVal::HashMapV(Gc::new(m.update(key, value)).into())),
55✔
185
            }
186
        } else {
187
            stop!(TypeMismatch => "hash-insert expects a hash map, found: {:?}", map);
×
188
        }
189
    } else {
190
        stop!(TypeMismatch => "hash key not hashable: {:?}", key)
×
191
    }
192
}
193

194
/// Gets the `key` from the given `map`. Raises an error if the key does not exist. `hash-get` is an alias for this.
195
///
196
/// (hash-ref map key) -> any/c
197
///
198
/// * map : hash?
199
/// * key : any/c
200
///
201
/// # Examples
202
/// ```scheme
203
/// > (hash-ref (hash 'a 10 'b 20) 'b) ;; => 20
204
/// ```
205
#[function(name = "hash-ref")]
206
pub fn hash_ref(map: &Gc<HashMap<SteelVal, SteelVal>>, key: &SteelVal) -> Result<SteelVal> {
31,384✔
207
    if key.is_hashable() {
62,768✔
208
        match map.get(key) {
62,768✔
209
            Some(value) => Ok(value.clone()),
62,766✔
210
            None => stop!(Generic => "key not found in hash map: {} - map: {:?}", key, map),
1✔
211
        }
212
    } else {
213
        stop!(TypeMismatch => "key not hashable: {}", key)
×
214
    }
215
}
216

217
/// Gets the `key` from the given `map`. Returns #false if the key does not exist.
218
///
219
/// (hash-try-get map key) -> (or any/c #false)
220
///
221
/// * map : hash?
222
/// * key : any/c
223
///
224
/// # Examples
225
///
226
/// ```scheme
227
/// > (hash-try-get (hash 'a 10 'b 20) 'b) ;; => 20
228
/// > (hash-try-get (hash 'a 10 'b 20) 'does-not-exist) ;; => #false
229
/// ```
230
#[function(name = "hash-try-get")]
231
pub fn hash_try_get(map: &Gc<HashMap<SteelVal, SteelVal>>, key: &SteelVal) -> SteelVal {
4,160✔
232
    match map.get(key) {
8,320✔
233
        Some(v) => v.clone(),
1,785✔
234
        None => SteelVal::BoolV(false),
3,565✔
235
    }
236
}
237

238
/// Returns the number of key value pairs in the map
239
///
240
/// (hash-length map) -> (and positive? int?)
241
///
242
/// * map : hash?
243
///
244
/// # Examples
245
///
246
/// ```scheme
247
/// > (hash-length (hash 'a 10 'b 20)) ;; => 2
248
/// ```
249
#[function(name = "hash-length")]
250
pub fn hash_length(map: &Gc<HashMap<SteelVal, SteelVal>>) -> usize {
×
251
    map.len()
×
252
}
253

254
/// Checks whether the given map contains the given key. Key must be hashable.
255
///
256
/// (hash-contains? map key) -> bool?
257
///
258
/// * map : hash?
259
/// * key : hashable?
260
///
261
/// # Example
262
///
263
/// ```scheme
264
/// > (hash-contains? (hash 'a 10 'b 20) 'a) ;; => #true
265
/// > (hash-contains? (hash 'a 10 'b 20) 'not-there) ;; => #false
266
/// ```
267
#[function(name = "hash-contains?")]
268
pub fn hash_contains(map: &Gc<HashMap<SteelVal, SteelVal>>, key: &SteelVal) -> Result<SteelVal> {
3✔
269
    if key.is_hashable() {
6✔
270
        Ok(SteelVal::BoolV(map.contains_key(key)))
6✔
271
    } else {
272
        stop!(TypeMismatch => "hash key not hashable!: {}", key);
×
273
    }
274
}
275

276
/// Returns the keys of the given hash map as a list.
277
///
278
/// ```scheme
279
/// (hash-keys->list map) -> (listof hashable?)
280
/// ```
281
///
282
/// * map : hash?
283
///
284
/// # Examples
285
///
286
/// ```scheme
287
/// > (hash-keys->list? (hash 'a 'b 20)) ;; => '(a b)
288
/// ```
289
#[function(name = "hash-keys->list")]
290
pub fn keys_to_list(hashmap: &Gc<HashMap<SteelVal, SteelVal>>) -> Result<SteelVal> {
×
291
    Ok(SteelVal::ListV(hashmap.keys().cloned().collect()))
×
292
}
293

294
/// Returns the values of the given hash map as a list
295
///
296
/// (hash-values->list? map) -> (listof any/c)?
297
///
298
/// map: hash?
299
///
300
/// # Examples
301
/// ```scheme
302
/// > (hash-values->list? (hash 'a 10 'b 20)),
303
///   => '(10 20)",
304
/// ```
305
#[steel_derive::function(name = "hash-values->list")]
306
pub fn values_to_list(hashmap: &Gc<HashMap<SteelVal, SteelVal>>) -> Result<SteelVal> {
×
307
    Ok(SteelVal::ListV(hashmap.values().cloned().collect()))
×
308
}
309

310
/// Returns the keys of the given hash map as an immutable vector
311
///
312
/// (hash-keys->vector map) -> (vectorof any/c)?
313
///
314
/// map: hash?
315
///
316
/// # Examples
317
/// ```scheme
318
/// > (hash-keys->vector (hash 'a 10 'b 20)),
319
///   => ['a 'b]",
320
/// ```
321
#[steel_derive::function(name = "hash-keys->vector")]
322
pub fn keys_to_vector(hashmap: &Gc<HashMap<SteelVal, SteelVal>>) -> Result<SteelVal> {
1✔
323
    vec_construct_iter_normal(hashmap.keys().cloned())
3✔
324
}
325

326
/// Returns the values of the given hash map as an immutable vector
327
///
328
/// (hash-values->vector map) -> (vectorof any/c)?
329
///
330
/// map: hash?
331
///
332
/// # Examples
333
/// ```scheme
334
/// > (hash-keys->vector (hash 'a 10 'b 20)),
335
///   => [10 10]",
336
/// ```
337
#[steel_derive::function(name = "hash-values->vector")]
338
pub fn values_to_vector(hashmap: &Gc<HashMap<SteelVal, SteelVal>>) -> Result<SteelVal> {
1✔
339
    vec_construct_iter_normal(hashmap.values().cloned())
3✔
340
}
341

342
/// Clears the entries out of the existing hashmap.
343
/// Will attempt to reuse the existing memory if there are no other references
344
/// to the hashmap.
345
///
346
/// (hash-clear h) -> hash?
347
///
348
/// h: hash?
349
///
350
/// # Examples
351
/// ```scheme
352
/// > (hash-clear (hash 'a 10 'b 20))
353
/// => '#hash()
354
/// ```
355
#[steel_derive::function(name = "hash-clear")]
356
pub fn clear(hashmap: &mut SteelVal) -> Result<SteelVal> {
×
357
    if let SteelVal::HashMapV(SteelHashMap(ref mut m)) = hashmap {
×
358
        match Gc::get_mut(m) {
359
            Some(m) => {
×
360
                // m.insert(key, value);
361
                m.clear();
×
362
                Ok(std::mem::replace(hashmap, SteelVal::Void))
×
363
            }
364
            None => Ok(SteelVal::HashMapV(Gc::new(HashMap::new()).into())),
×
365
        }
366
    } else {
367
        stop!(TypeMismatch => "hash-clear expected a hashmap, found: {:?}", hashmap);
×
368
    }
369
}
370

371
/// Checks whether the hash map is empty
372
///
373
/// (hash-empty? m) -> bool?
374
///
375
/// m: hash?
376
///
377
/// # Examples
378
/// ```scheme
379
/// > (hash-empty? (hash 'a 10)) ;; => #f
380
/// > (hash-emptY? (hash)) ;; => #true
381
/// ```
382
#[steel_derive::function(name = "hash-empty?")]
383
pub fn hm_empty(hm: &Gc<HashMap<SteelVal, SteelVal>>) -> Result<SteelVal> {
×
384
    Ok(SteelVal::BoolV(hm.is_empty()))
×
385
}
386

387
/// Constructs the union of two hashmaps, keeping the values
388
/// in the left map when the keys exist in both maps.
389
///
390
/// Will reuse memory where possible.
391
///
392
/// (hash-union l r) -> hash?
393
///
394
/// # Examples
395
/// ```scheme
396
/// > (hash-union (hash 'a 10) (hash 'b 20)) ;; => '#hash((a . 10) (b . 20))
397
/// ```
398
#[steel_derive::function(name = "hash-union")]
399
pub fn hm_union(mut hml: &mut SteelVal, mut hmr: &mut SteelVal) -> Result<SteelVal> {
1,359✔
400
    match (&mut hml, &mut hmr) {
2,718✔
401
        (
402
            SteelVal::HashMapV(SteelHashMap(ref mut l)),
1,359✔
403
            SteelVal::HashMapV(SteelHashMap(ref mut r)),
404
        ) => match (Gc::get_mut(l), Gc::get_mut(r)) {
405
            (None, None) => {
406
                let hml = l.unwrap();
×
407
                let hmr = r.unwrap();
408
                Ok(SteelVal::HashMapV(Gc::new(hml.union(hmr)).into()))
409
            }
410
            (None, Some(r_map)) => {
×
411
                let right_side_value = std::mem::take(r_map);
×
412

413
                *r_map = l.unwrap().union(right_side_value);
×
414

NEW
415
                Ok(std::mem::replace(hmr, SteelVal::Void))
×
416
            }
417
            (Some(l_map), None) => {
×
418
                let left_side_value = std::mem::take(l_map);
419

420
                *l_map = left_side_value.union(r.unwrap());
421

422
                Ok(std::mem::replace(hml, SteelVal::Void))
423
            }
424
            (Some(l_map), Some(r_map)) => {
2,718✔
425
                let left_side_value = std::mem::take(l_map);
4,077✔
426
                let right_side_value = std::mem::take(r_map);
4,077✔
427

428
                *l_map = left_side_value.union(right_side_value);
5,436✔
429

430
                Ok(std::mem::replace(hml, SteelVal::Void))
2,718✔
431
            }
432
        },
433

434
        _ => {
435
            stop!(TypeMismatch => "hash-union expects two hash maps, found: {:?} and {:?}", hml, hmr)
×
436
        }
437
    }
438
}
439

440
#[cfg(test)]
441
mod hashmap_tests {
442
    use super::*;
443

444
    #[cfg(not(feature = "sync"))]
445
    use im_rc::hashmap;
446

447
    #[cfg(not(feature = "sync"))]
448
    use im_rc::vector;
449

450
    #[cfg(all(feature = "sync", not(feature = "imbl")))]
451
    use im::hashmap;
452

453
    #[cfg(all(feature = "sync", not(feature = "imbl")))]
454
    use im::vector;
455

456
    #[cfg(all(feature = "sync", feature = "imbl"))]
457
    use imbl::hashmap;
458

459
    #[cfg(all(feature = "sync", feature = "imbl"))]
460
    use imbl::vector;
461

462
    use crate::rvals::{SteelString, SteelVal::*};
463

464
    #[test]
465
    fn hm_construct_normal() {
466
        let args = [
467
            StringV("foo".into()),
468
            StringV("bar".into()),
469
            StringV("foo2".into()),
470
            StringV("bar2".into()),
471
        ];
472
        let res = hm_construct(&args);
473
        let expected = SteelVal::HashMapV(
474
            Gc::new(hashmap! {
475
                StringV("foo".into()) => StringV("bar".into()),
476
                StringV("foo2".into()) => StringV("bar2".into())
477
            })
478
            .into(),
479
        );
480
        assert_eq!(res.unwrap(), expected);
481
    }
482

483
    #[test]
484
    fn hm_construct_with_duplicates() {
485
        let args = [
486
            StringV("foo".into()),
487
            StringV("bar".into()),
488
            StringV("foo2".into()),
489
            StringV("bar2".into()),
490
            StringV("foo".into()),
491
            StringV("bar".into()),
492
            StringV("foo2".into()),
493
            StringV("bar2".into()),
494
        ];
495
        let res = hm_construct(&args);
496
        let expected = SteelVal::HashMapV(
497
            Gc::new(hashmap! {
498
                StringV("foo".into()) => StringV("bar".into()),
499
                StringV("foo2".into()) => StringV("bar2".into())
500
            })
501
            .into(),
502
        );
503
        assert_eq!(res.unwrap(), expected);
504
    }
505

506
    #[test]
507
    fn hm_insert_from_empty() {
508
        let mut args = [
509
            HashMapV(Gc::new(hashmap![]).into()),
510
            StringV("foo".into()),
511
            StringV("bar".into()),
512
        ];
513
        let res = steel_hash_insert(&mut args);
514
        let expected = SteelVal::HashMapV(
515
            Gc::new(hashmap! {
516
                StringV("foo".into()) => StringV("bar".into())
517
            })
518
            .into(),
519
        );
520
        assert_eq!(res.unwrap(), expected);
521
    }
522

523
    #[test]
524
    fn hm_get_found() {
525
        let args = [
526
            HashMapV(
527
                Gc::new(hashmap! {
528
                    StringV("foo".into()) => StringV("bar".into())
529
                })
530
                .into(),
531
            ),
532
            StringV("foo".into()),
533
        ];
534
        let res = steel_hash_ref(&args);
535
        let expected = StringV("bar".into());
536
        assert_eq!(res.unwrap(), expected);
537
    }
538

539
    #[test]
540
    fn hm_get_error() {
541
        let args = [
542
            HashMapV(
543
                Gc::new(hashmap! {
544
                    StringV("foo".into()) => StringV("bar".into())
545
                })
546
                .into(),
547
            ),
548
            StringV("garbage".into()),
549
        ];
550
        let res = steel_hash_ref(&args);
551
        assert!(res.is_err());
552
    }
553

554
    #[test]
555
    fn hm_try_get_found() {
556
        let args = [
557
            HashMapV(
558
                Gc::new(hashmap! {
559
                    StringV("foo".into()) => StringV("bar".into())
560
                })
561
                .into(),
562
            ),
563
            StringV("foo".into()),
564
        ];
565
        let res = steel_hash_try_get(&args);
566
        let expected = StringV("bar".into());
567
        assert_eq!(res.unwrap(), expected);
568
    }
569

570
    #[test]
571
    fn hm_try_get_error() {
572
        let args = [
573
            HashMapV(
574
                Gc::new(hashmap! {
575
                    StringV("foo".into()) => StringV("bar".into())
576
                })
577
                .into(),
578
            ),
579
            StringV("garbage".into()),
580
        ];
581
        let res = steel_hash_contains(&args);
582
        let expected = SteelVal::BoolV(false);
583
        assert_eq!(res.unwrap(), expected);
584
    }
585

586
    #[test]
587
    fn hm_contains_true() {
588
        let args = [
589
            HashMapV(
590
                Gc::new(hashmap! {
591
                    StringV("foo".into()) => StringV("bar".into())
592
                })
593
                .into(),
594
            ),
595
            StringV("foo".into()),
596
        ];
597
        let res = steel_hash_contains(&args);
598
        let expected = SteelVal::BoolV(true);
599
        assert_eq!(res.unwrap(), expected);
600
    }
601

602
    #[test]
603
    fn hm_contains_false() {
604
        let args = [
605
            HashMapV(
606
                Gc::new(hashmap! {
607
                    StringV("foo".into()) => StringV("bar".into())
608
                })
609
                .into(),
610
            ),
611
            StringV("bar".into()),
612
        ];
613
        let res = steel_hash_contains(&args);
614
        let expected = SteelVal::BoolV(false);
615
        assert_eq!(res.unwrap(), expected);
616
    }
617

618
    #[test]
619
    fn hm_keys_to_vector_normal() {
620
        let args = vec![HashMapV(
621
            Gc::new(hashmap! {
622
                StringV("foo".into()) => StringV("bar".into()),
623
                StringV("bar".into()) => StringV("baz".into()),
624
                StringV("baz".into()) => StringV("quux".into())
625
            })
626
            .into(),
627
        )];
628
        let res = steel_keys_to_vector(&args);
629
        let expected = vector![
630
            SteelVal::StringV("foo".into()),
631
            SteelVal::StringV("bar".into()),
632
            SteelVal::StringV("baz".into()),
633
        ]
634
        .into();
635

636
        // pull out the vectors and sort them
637
        // let unwrapped_res: SteelVal = (*res.unwrap()).clone();
638
        // let unwrapped_expected: SteelVal = (*expected).clone();
639

640
        let mut res_vec_string: Vec<SteelString> = if let SteelVal::VectorV(v) = res.unwrap() {
641
            v.iter()
642
                .map(|x| {
643
                    if let SteelVal::StringV(ref s) = x {
644
                        s.clone()
645
                    } else {
646
                        panic!("test failed")
647
                    }
648
                })
649
                .collect()
650
        } else {
651
            panic!("test failed")
652
        };
653

654
        let mut expected_vec_string: Vec<SteelString> = if let SteelVal::VectorV(v) = expected {
655
            v.iter()
656
                .map(|x| {
657
                    if let SteelVal::StringV(ref s) = x {
658
                        s.clone()
659
                    } else {
660
                        panic!("test failed")
661
                    }
662
                })
663
                .collect()
664
        } else {
665
            panic!("test failed")
666
        };
667

668
        res_vec_string.sort();
669
        expected_vec_string.sort();
670

671
        assert_eq!(res_vec_string, expected_vec_string);
672
    }
673

674
    #[test]
675
    fn hm_values_to_vector_normal() {
676
        let args = vec![HashMapV(
677
            Gc::new(hashmap! {
678
                StringV("foo".into()) => StringV("bar".into()),
679
                StringV("bar".into()) => StringV("baz".into()),
680
                StringV("baz".into()) => StringV("quux".into())
681
            })
682
            .into(),
683
        )];
684
        let res = steel_values_to_vector(&args);
685
        let expected = vector![
686
            SteelVal::StringV("bar".into()),
687
            SteelVal::StringV("baz".into()),
688
            SteelVal::StringV("quux".into()),
689
        ]
690
        .into();
691

692
        // pull out the vectors and sort them
693

694
        let mut res_vec_string: Vec<SteelString> = if let SteelVal::VectorV(v) = res.unwrap() {
695
            v.iter()
696
                .map(|x| {
697
                    if let SteelVal::StringV(ref s) = x {
698
                        s.clone()
699
                    } else {
700
                        panic!("test failed")
701
                    }
702
                })
703
                .collect()
704
        } else {
705
            panic!("test failed")
706
        };
707

708
        let mut expected_vec_string: Vec<SteelString> = if let SteelVal::VectorV(v) = expected {
709
            v.iter()
710
                .map(|x| {
711
                    if let SteelVal::StringV(ref s) = x {
712
                        s.clone()
713
                    } else {
714
                        panic!("test failed")
715
                    }
716
                })
717
                .collect()
718
        } else {
719
            panic!("test failed")
720
        };
721

722
        res_vec_string.sort();
723
        expected_vec_string.sort();
724

725
        assert_eq!(res_vec_string, expected_vec_string);
726
    }
727
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc