1use crate::{
2 tap_config::TapConfig,
3 tap_error::TapError,
4 TapReaderBuilder,
6 TapShape,
7};
8use serde::{Deserialize, Serialize};
9use std::{fmt::Display, io, path::Path};
10use tracing::{debug, info};
11
12#[derive(Debug, Serialize, Deserialize)]
13struct TapShapeId(String);
14
15#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
16pub struct DCTap {
17 version: String,
18
19 shapes: Vec<TapShape>,
20}
21
22impl Default for DCTap {
23 fn default() -> Self {
24 Self::new()
25 }
26}
27
28impl DCTap {
29 pub fn new() -> DCTap {
30 DCTap {
31 version: "0.1".to_string(),
32 shapes: Vec::new(),
33 }
34 }
35
36 pub fn add_shape(&mut self, shape: &TapShape) {
37 self.shapes.push(shape.clone());
38 }
39
40 pub fn from_path<P: AsRef<Path>>(path: P, config: &TapConfig) -> Result<DCTap, TapError> {
41 let mut dctap = DCTap::new();
42 let mut tap_reader = TapReaderBuilder::from_path(path, config)?;
43 for maybe_shape in tap_reader.shapes() {
44 let shape = maybe_shape?;
45 dctap.add_shape(&shape)
46 }
47 if tap_reader.has_warnings() {
48 for warning in tap_reader.warnings() {
49 info!("Warning: {warning}");
50 }
51 }
52 Ok(dctap)
53 }
54
55 pub fn from_reader<R: io::Read>(reader: R, config: &TapConfig) -> Result<DCTap, TapError> {
56 let mut dctap = DCTap::new();
57 debug!("DCTap parsed: {:?}", dctap);
58 let mut tap_reader = TapReaderBuilder::from_reader(reader, config)?;
59 for maybe_shape in tap_reader.shapes() {
60 let shape = maybe_shape?;
61 dctap.add_shape(&shape)
62 }
63 Ok(dctap)
64 }
65
66 pub fn shapes(&self) -> impl Iterator<Item = &TapShape> {
83 self.shapes.iter()
84 }
85}
86
87impl Display for DCTap {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 for shape in self.shapes() {
90 write!(f, "{shape}")?;
91 }
92 Ok(())
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use crate::{PropertyId, ShapeId, TapShape, TapStatement};
99
100 use super::*;
101
102 #[test]
103 fn test_simple() {
104 let data = "\
105shapeId,shapeLabel,propertyId,propertyLabel
106Person,PersonLabel,knows,knowsLabel
107";
108 let dctap = DCTap::from_reader(data.as_bytes(), &TapConfig::default()).unwrap();
109 let mut expected_shape = TapShape::new(2);
110 expected_shape.set_shape_id(&ShapeId::new("Person", 2));
111 expected_shape.set_shape_label("PersonLabel");
112 let mut statement =
113 TapStatement::new(PropertyId::new("knows", 2)).with_source_line_number(2);
114 statement.set_property_label("knowsLabel");
115 expected_shape.add_statement(statement);
116 let mut expected_dctap = DCTap::new();
117 expected_dctap.add_shape(&expected_shape);
118 assert_eq!(dctap, expected_dctap);
119 }
120}