Skip to content

Commit c8a2d79

Browse files
committed
Adding rotate_through_iterators for select_phantom_hints refactor
- adding function to allow for select_phantom_hints to yield an iterator
1 parent 4dce209 commit c8a2d79

File tree

1 file changed

+134
-1
lines changed

1 file changed

+134
-1
lines changed

lightning-invoice/src/utils.rs

+134-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use lightning::util::logger::Logger;
1818
use secp256k1::PublicKey;
1919
use core::ops::Deref;
2020
use core::time::Duration;
21+
use core::iter::Iterator;
2122

2223
/// Utility to create an invoice that can be paid to one of multiple nodes, or a "phantom invoice."
2324
/// See [`PhantomKeysManager`] for more information on phantom node payments.
@@ -292,6 +293,31 @@ where
292293
}
293294
}
294295

296+
/// Draw items iteratively from multiple iterators. The items are retrieved by index and
297+
/// rotates through the iterators - first the zero index then the first index then second index, etc.
298+
fn rotate_through_iterators<T, I: Iterator<Item = T>>(mut vecs: Vec<I>) -> impl Iterator<Item = T> {
299+
let mut iterations = 0;
300+
301+
core::iter::from_fn(move || {
302+
let mut exhausted_iterators = 0;
303+
loop {
304+
if vecs.is_empty() {
305+
return None;
306+
}
307+
let next_idx = iterations % vecs.len();
308+
iterations += 1;
309+
if let Some(item) = vecs[next_idx].next() {
310+
return Some(item);
311+
}
312+
// exhausted_vectors increase when the "next_idx" vector is exhausted
313+
exhausted_iterators += 1;
314+
// The check for exhausted iterators gets reset to 0 after each yield of `Some()`
315+
// The lop will return None when all of the nested iterators are exhausted
316+
if exhausted_iterators == vecs.len() {
317+
return None;
318+
}
319+
}
320+
})
295321
#[cfg(feature = "std")]
296322
/// Utility to construct an invoice. Generally, unless you want to do something like a custom
297323
/// cltv_expiry, this is what you should be using to create an invoice. The reason being, this
@@ -777,7 +803,7 @@ mod test {
777803
use lightning::routing::router::{PaymentParameters, RouteParameters};
778804
use lightning::util::test_utils;
779805
use lightning::util::config::UserConfig;
780-
use crate::utils::create_invoice_from_channelmanager_and_duration_since_epoch;
806+
use crate::utils::{create_invoice_from_channelmanager_and_duration_since_epoch, rotate_through_iterators};
781807
use std::collections::HashSet;
782808

783809
#[test]
@@ -1886,4 +1912,111 @@ mod test {
18861912
_ => panic!(),
18871913
}
18881914
}
1915+
1916+
#[test]
1917+
fn test_rotate_through_iterators() {
1918+
// two nested vectors
1919+
let a = vec![vec!["a0", "b0", "c0"].into_iter(), vec!["a1", "b1"].into_iter()];
1920+
let result = rotate_through_iterators(a).collect::<Vec<_>>();
1921+
1922+
let expected = vec!["a0", "a1", "b0", "b1", "c0"];
1923+
assert_eq!(expected, result);
1924+
1925+
// test single nested vector
1926+
let a = vec![vec!["a0", "b0", "c0"].into_iter()];
1927+
let result = rotate_through_iterators(a).collect::<Vec<_>>();
1928+
1929+
let expected = vec!["a0", "b0", "c0"];
1930+
assert_eq!(expected, result);
1931+
1932+
// test second vector with only one element
1933+
let a = vec![vec!["a0", "b0", "c0"].into_iter(), vec!["a1"].into_iter()];
1934+
let result = rotate_through_iterators(a).collect::<Vec<_>>();
1935+
1936+
let expected = vec!["a0", "a1", "b0", "c0"];
1937+
assert_eq!(expected, result);
1938+
1939+
// test three nestend vectors
1940+
let a = vec![vec!["a0"].into_iter(), vec!["a1", "b1", "c1"].into_iter(), vec!["a2"].into_iter()];
1941+
let result = rotate_through_iterators(a).collect::<Vec<_>>();
1942+
1943+
let expected = vec!["a0", "a1", "a2", "b1", "c1"];
1944+
assert_eq!(expected, result);
1945+
1946+
// test single nested vector with a single value
1947+
let a = vec![vec!["a0"].into_iter()];
1948+
let result = rotate_through_iterators(a).collect::<Vec<_>>();
1949+
1950+
let expected = vec!["a0"];
1951+
assert_eq!(expected, result);
1952+
1953+
// test single empty nested vector
1954+
let a:Vec<std::vec::IntoIter<&str>> = vec![vec![].into_iter()];
1955+
let result = rotate_through_iterators(a).collect::<Vec<&str>>();
1956+
let expected:Vec<&str> = vec![];
1957+
1958+
assert_eq!(expected, result);
1959+
1960+
// test first nested vector is empty
1961+
let a:Vec<std::vec::IntoIter<&str>>= vec![vec![].into_iter(), vec!["a1", "b1", "c1"].into_iter()];
1962+
let result = rotate_through_iterators(a).collect::<Vec<&str>>();
1963+
1964+
let expected = vec!["a1", "b1", "c1"];
1965+
assert_eq!(expected, result);
1966+
1967+
// test two empty vectors
1968+
let a:Vec<std::vec::IntoIter<&str>> = vec![vec![].into_iter(), vec![].into_iter()];
1969+
let result = rotate_through_iterators(a).collect::<Vec<&str>>();
1970+
1971+
let expected:Vec<&str> = vec![];
1972+
assert_eq!(expected, result);
1973+
1974+
// test an empty vector amongst other filled vectors
1975+
let a = vec![
1976+
vec!["a0", "b0", "c0"].into_iter(),
1977+
vec![].into_iter(),
1978+
vec!["a1", "b1", "c1"].into_iter(),
1979+
vec!["a2", "b2", "c2"].into_iter(),
1980+
];
1981+
let result = rotate_through_iterators(a).collect::<Vec<_>>();
1982+
1983+
let expected = vec!["a0", "a1", "a2", "b0", "b1", "b2", "c0", "c1", "c2"];
1984+
assert_eq!(expected, result);
1985+
1986+
// test a filled vector between two empty vectors
1987+
let a = vec![vec![].into_iter(), vec!["a1", "b1", "c1"].into_iter(), vec![].into_iter()];
1988+
let result = rotate_through_iterators(a).collect::<Vec<_>>();
1989+
1990+
let expected = vec!["a1", "b1", "c1"];
1991+
assert_eq!(expected, result);
1992+
1993+
// test an empty vector at the end of the vectors
1994+
let a = vec![vec!["a0", "b0", "c0"].into_iter(), vec![].into_iter()];
1995+
let result = rotate_through_iterators(a).collect::<Vec<_>>();
1996+
1997+
let expected = vec!["a0", "b0", "c0"];
1998+
assert_eq!(expected, result);
1999+
2000+
// test multiple empty vectors amongst multiple filled vectors
2001+
let a = vec![
2002+
vec![].into_iter(),
2003+
vec!["a1", "b1", "c1"].into_iter(),
2004+
vec![].into_iter(),
2005+
vec!["a3", "b3"].into_iter(),
2006+
vec![].into_iter(),
2007+
];
2008+
2009+
let result = rotate_through_iterators(a).collect::<Vec<_>>();
2010+
2011+
let expected = vec!["a1", "a3", "b1", "b3", "c1"];
2012+
assert_eq!(expected, result);
2013+
2014+
// test one element in the first nested vectore and two elements in the second nested
2015+
// vector
2016+
let a = vec![vec!["a0"].into_iter(), vec!["a1", "b1"].into_iter()];
2017+
let result = rotate_through_iterators(a).collect::<Vec<_>>();
2018+
2019+
let expected = vec!["a0", "a1", "b1"];
2020+
assert_eq!(expected, result);
2021+
}
18892022
}

0 commit comments

Comments
 (0)