asimov_protocol/handle_resolvers/
csv_handle_resolver.rs1use crate::{PeerId, ResolveHandle};
4use alloc::string::String;
5use asimov_id::Handle;
6use core::str::FromStr;
7use csv_async::{AsyncReader, AsyncReaderBuilder, StringRecord};
8use futures_lite::{Stream, StreamExt, pin, stream};
9use iroh::EndpointId;
10use std::io::{Error, Result};
11use tokio::fs::File;
12use tokio::io::AsyncReadExt;
13
14#[cfg(not(feature = "std"))]
15use alloc::collections::BTreeSet as Set;
16
17#[cfg(feature = "std")]
18use std::collections::HashSet as Set;
19
20pub struct CsvHandleResolver(AsyncReader<File>);
26
27impl CsvHandleResolver {
28 pub async fn open(path: &str) -> std::io::Result<Self> {
30 let file = File::open(path).await?;
31 let reader = AsyncReaderBuilder::new()
32 .has_headers(false)
33 .create_reader(file);
34 Ok(Self::from(reader))
35 }
36
37 pub fn handles(&mut self) -> impl Stream<Item = Result<Handle>> + Send {
38 async_stream::stream! {
39 let mut handles = Set::new();
40 let records = self.records();
41 pin!(records);
42 while let Some(record) = records.next().await {
43 let (handle, _) = record?;
44 if handles.contains(&handle) {
45 continue; }
47 handles.insert(handle.clone());
48 yield Ok(handle);
49 }
50 }
51 }
52
53 pub fn records(&mut self) -> impl Stream<Item = Result<(Handle, PeerId)>> + Send {
54 async_stream::stream! {
55 self.0.rewind().await?;
56 let mut record = StringRecord::new();
57 while let Ok(true) = self.0.read_record(&mut record).await {
58 let Some(record_handle) = record.get(0) else {
59 continue; };
61 let Some(record_endpoint) = record.get(1) else {
62 continue; };
64 let Ok(handle) = record_handle.parse::<Handle>() else {
65 continue; };
67 let Ok(endpoint) = record_endpoint.parse::<PeerId>() else {
68 continue; };
70 yield Ok((handle, endpoint));
71 }
72 }
73 }
74}
75
76impl From<AsyncReader<File>> for CsvHandleResolver {
77 fn from(reader: AsyncReader<File>) -> Self {
78 Self(reader)
79 }
80}
81
82impl ResolveHandle for CsvHandleResolver {
83 type Error = std::io::Error;
84
85 fn resolve_handle(
87 &mut self,
88 handle: impl Into<Handle>,
89 ) -> impl Stream<Item = Result<PeerId>> + Send {
90 let handle = handle.into();
91 async_stream::stream! {
92 let mut endpoints = Set::new();
93 let records = self.records();
94 pin!(records);
95 while let Some(record) = records.next().await {
96 let (record_handle, record_endpoint) = record?;
97 if record_handle != handle {
98 continue; }
100 if endpoints.contains(&record_endpoint) {
101 continue; }
103 endpoints.insert(record_endpoint.clone());
104 yield Ok(record_endpoint);
105 }
106 }
107 }
108}