1use crate::*;
26
27use std::{
28 fmt,
29 io::{BufRead, Error as ioError, Write},
30};
31
32use super::{types::*, utils::*};
33
34pub fn save_xy<RA, P, W>(write: &mut W, ra: &RA, delim_coord: &str, delim_pos: &str) -> XyResult<()>
38where
39 RA: IsRandomAccessible<P>,
40 P: Is2D,
41 W: Write,
42{
43 let n = ra.len();
44 for i in 0..n {
45 let ref p = ra[i];
46 let buffer = p.x().to_string() + delim_coord + &p.y().to_string() + delim_pos;
47 write.write_all(buffer.as_bytes())?;
48 }
49 Ok(())
50}
51
52pub fn load_xy<IP, P, R>(read: &mut R, ip: &mut IP) -> XyIOResult<()>
54where
55 IP: IsPushable<P>,
56 P: IsBuildable2D,
57 R: BufRead,
58{
59 let mut delim_determined = false;
60 let mut delim = 0;
61 let mut line_buffer = Vec::new();
62
63 let mut i_line = 0;
64
65 while let Ok(line) = fetch_line(read, &mut line_buffer) {
66 i_line += 1;
67
68 if !delim_determined {
69 delim = estimate_delimiter(1, line)
70 .ok_or(XyError::EstimateDelimiter)
71 .line(i_line, line)?;
72
73 delim_determined = true;
74 }
75
76 let mut words = line.split(|x| *x == delim).skip_empty();
77
78 let x = words
79 .next()
80 .and_then(|word| from_ascii(word))
81 .ok_or(XyError::Vertex)
82 .line(i_line, line)?;
83
84 let y = words
85 .next()
86 .and_then(|word| from_ascii(word))
87 .ok_or(XyError::Vertex)
88 .line(i_line, line)?;
89
90 ip.push(P::new(x, y));
91 }
92
93 Ok(())
94}
95
96pub enum XyError {
100 EstimateDelimiter,
101 AccessFile,
102 Vertex,
103}
104
105pub type XyResult<T> = std::result::Result<T, XyError>;
107
108pub type XyIOResult<T> = IOResult<T, XyError>;
110
111impl fmt::Debug for XyError {
112 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
113 match self {
114 Self::Vertex => write!(f, "Unable to parse vertex"),
115 Self::AccessFile => write!(f, "Unable to access file"),
116 Self::EstimateDelimiter => write!(f, "Unable to estimate delimiter"),
117 }
118 }
119}
120
121impl fmt::Display for XyError {
122 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
123 write!(f, "{:?}", self)
124 }
125}
126
127impl From<ioError> for XyError {
128 fn from(_error: ioError) -> Self {
129 XyError::AccessFile
130 }
131}