1use std::{fmt, str::FromStr};
2
3use num_traits::{Float, Unsigned};
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7use crate::{error::weak_error, DefaultFloat, DefaultUnsigned, Error};
8
9pub(crate) const NODE_TAG: &str = "ND";
10
11#[derive(Copy, Clone, Debug, PartialEq)]
15#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
16pub struct Node<U = DefaultUnsigned, F = DefaultFloat>
17where
18 U: Unsigned + Copy + fmt::Debug,
19 F: Float + fmt::Debug,
20 Error: From<U::FromStrRadixErr> + From<F::FromStrRadixErr>,
21{
22 pub id: U,
24 pub coordinate: [F; 3],
26}
27impl<U, F> FromStr for Node<U, F>
28where
29 U: Unsigned + Copy + fmt::Debug,
30 F: Float + fmt::Debug,
31 Error: From<U::FromStrRadixErr> + From<F::FromStrRadixErr>,
32{
33 type Err = Error;
34
35 fn from_str(s: &str) -> Result<Self, Self::Err> {
36 let mut field_it = s.split_whitespace();
37
38 match field_it.next() {
39 Some(NODE_TAG) => {} Some(t) => Err(Error::WrongCardTag {
41 expect: NODE_TAG.into(),
42 actual: t.into(),
43 })?,
44 None => Err(Error::EmptyLine)?,
45 }
46
47 let id_raw = field_it.next().ok_or(Error::MissingValue)?;
48 let id = U::from_str_radix(id_raw, 10)?;
49
50 let mut coordinate = [F::zero(); 3];
51 for component in coordinate.iter_mut() {
52 let Some(c_raw) = field_it.next() else {
53 Err(Error::MissingValue)?
54 };
55 *component = F::from_str_radix(c_raw, 10)?;
56 }
57
58 if let Some(v) = field_it.next() {
59 weak_error(Error::ExtraneousValue(v.into()))?;
60 }
61
62 Ok(Self { id, coordinate })
63 }
64}