2022-08-30 16:53:34 +00:00
|
|
|
use std::fs::File;
|
|
|
|
use std::io::Read;
|
2022-10-28 20:39:47 +00:00
|
|
|
use std::io::{self, BufRead};
|
|
|
|
use std::{collections::HashMap, io::BufReader};
|
2022-08-30 16:53:34 +00:00
|
|
|
|
2022-12-06 21:16:36 +00:00
|
|
|
use crate::types::edge::EdgeDB;
|
2022-08-30 21:30:38 +00:00
|
|
|
use crate::types::{Address, Edge, U256};
|
2022-08-30 16:53:34 +00:00
|
|
|
|
2022-12-06 21:16:36 +00:00
|
|
|
pub fn read_edges_binary(path: &String) -> Result<EdgeDB, io::Error> {
|
2022-08-30 16:53:34 +00:00
|
|
|
let mut f = File::open(path)?;
|
|
|
|
let address_index = read_address_index(&mut f)?;
|
|
|
|
read_edges(&mut f, &address_index)
|
|
|
|
}
|
|
|
|
|
2022-12-06 21:16:36 +00:00
|
|
|
pub fn read_edges_csv(path: &String) -> Result<EdgeDB, io::Error> {
|
|
|
|
let mut edges = Vec::new();
|
2022-10-28 20:39:47 +00:00
|
|
|
let f = BufReader::new(File::open(path)?);
|
|
|
|
for line in f.lines() {
|
|
|
|
let line = line?;
|
|
|
|
match &line.split(',').collect::<Vec<_>>()[..] {
|
|
|
|
[] => continue,
|
|
|
|
[from, to, token, capacity] => {
|
|
|
|
let from = Address::from(unescape(from));
|
|
|
|
let to = Address::from(unescape(to));
|
|
|
|
let token = Address::from(unescape(token));
|
|
|
|
let capacity = U256::from(unescape(capacity));
|
2022-12-06 21:16:36 +00:00
|
|
|
edges.push(Edge {
|
2022-10-28 20:39:47 +00:00
|
|
|
from,
|
|
|
|
to,
|
|
|
|
token,
|
|
|
|
capacity,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
return Result::Err(io::Error::new(
|
|
|
|
io::ErrorKind::Other,
|
|
|
|
format!("Expected from,to,token,capacity, but got {line}"),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-12-06 21:16:36 +00:00
|
|
|
Ok(EdgeDB::new(edges))
|
2022-10-28 20:39:47 +00:00
|
|
|
}
|
|
|
|
|
2022-08-30 16:53:34 +00:00
|
|
|
fn read_address_index(file: &mut File) -> Result<HashMap<u32, Address>, io::Error> {
|
|
|
|
let address_count = read_u32(file)?;
|
|
|
|
let mut addresses = HashMap::new();
|
|
|
|
for i in 0..address_count {
|
|
|
|
let mut buf = [0; 20];
|
|
|
|
file.read_exact(&mut buf)?;
|
|
|
|
addresses.insert(i, Address::from(buf));
|
|
|
|
}
|
|
|
|
Ok(addresses)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_u32(file: &mut File) -> Result<u32, io::Error> {
|
|
|
|
let mut buf = [0; 4];
|
|
|
|
file.read_exact(&mut buf)?;
|
|
|
|
Ok(u32::from_be_bytes(buf))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_u8(file: &mut File) -> Result<u8, io::Error> {
|
|
|
|
let mut buf = [0; 1];
|
|
|
|
file.read_exact(&mut buf)?;
|
|
|
|
Ok(u8::from_be_bytes(buf))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_address(
|
|
|
|
file: &mut File,
|
|
|
|
address_index: &HashMap<u32, Address>,
|
|
|
|
) -> Result<Address, io::Error> {
|
|
|
|
let index = read_u32(file)?;
|
|
|
|
Ok(address_index[&index])
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_u256(file: &mut File) -> Result<U256, io::Error> {
|
|
|
|
let length = read_u8(file)? as usize;
|
|
|
|
let mut bytes = [0u8; 32];
|
|
|
|
file.read_exact(&mut bytes[32 - length..32])?;
|
|
|
|
let high = u128::from_be_bytes(*<&[u8; 16]>::try_from(&bytes[0..16]).unwrap());
|
2022-09-01 21:04:36 +00:00
|
|
|
let low = u128::from_be_bytes(*<&[u8; 16]>::try_from(&bytes[16..32]).unwrap());
|
2022-08-30 16:53:34 +00:00
|
|
|
Ok(U256::new(high, low))
|
|
|
|
}
|
|
|
|
|
2022-12-06 21:16:36 +00:00
|
|
|
fn read_edges(file: &mut File, address_index: &HashMap<u32, Address>) -> Result<EdgeDB, io::Error> {
|
2022-08-30 16:53:34 +00:00
|
|
|
let edge_count = read_u32(file)?;
|
2022-12-06 21:16:36 +00:00
|
|
|
let mut edges = Vec::new();
|
2022-08-30 16:53:34 +00:00
|
|
|
for _i in 0..edge_count {
|
|
|
|
let from = read_address(file, address_index)?;
|
|
|
|
let to = read_address(file, address_index)?;
|
|
|
|
let token = read_address(file, address_index)?;
|
|
|
|
let capacity = read_u256(file)?;
|
2022-12-06 21:16:36 +00:00
|
|
|
edges.push(Edge {
|
2022-08-30 16:53:34 +00:00
|
|
|
from,
|
|
|
|
to,
|
|
|
|
token,
|
|
|
|
capacity,
|
|
|
|
});
|
|
|
|
}
|
2022-12-06 21:16:36 +00:00
|
|
|
Ok(EdgeDB::new(edges))
|
2022-08-30 16:53:34 +00:00
|
|
|
}
|
2022-10-28 20:39:47 +00:00
|
|
|
|
|
|
|
fn unescape(input: &str) -> &str {
|
|
|
|
match input.chars().next() {
|
|
|
|
Some('"') | Some('\'') => {
|
|
|
|
assert!(input.len() >= 2 && input.chars().last() == input.chars().next());
|
|
|
|
&input[1..input.len() - 1]
|
|
|
|
}
|
|
|
|
_ => input,
|
|
|
|
}
|
|
|
|
}
|