Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dctap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ repository.workspace = true

[dependencies]
csv = "1.3.0"
indexmap = { version = "2"}
serde = "1.0"
serde_derive = "1.0"

thiserror = "1"
tracing = "0.1"
58 changes: 53 additions & 5 deletions dctap/src/dctap.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
use crate::{tap_config::TapConfig, tap_error::TapError};
use crate::{tap_config::TapConfig, tap_error::TapError, ShapeId, TapReaderBuilder, TapShape};
use indexmap::IndexMap;
use serde_derive::{Deserialize, Serialize};
use std::path::Path;
use std::{io, path::Path};
use tracing::debug;

#[derive(Debug, Serialize, Deserialize)]
struct TapShapeId(String);

#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, PartialEq)]
pub struct DCTap {
version: String,
shapes: IndexMap<Option<ShapeId>, TapShape>,
}

impl Default for DCTap {
Expand All @@ -21,12 +23,58 @@ impl DCTap {
pub fn new() -> DCTap {
DCTap {
version: "0.1".to_string(),
shapes: IndexMap::new(),
}
}

pub fn read_buf(_path: &Path, _config: TapConfig) -> Result<DCTap, TapError> {
let dctap = DCTap::new();
pub fn add_shape(&mut self, shape: &TapShape) {
self.shapes.insert(shape.shape_id(), shape.clone());
}

pub fn from_path(path: &Path, _config: TapConfig) -> Result<DCTap, TapError> {
let mut dctap = DCTap::new();
debug!("DCTap parsed: {:?}", dctap);
let mut tap_reader = TapReaderBuilder::new().flexible(true).from_path(path)?;
for maybe_shape in tap_reader.shapes() {
let shape = maybe_shape?;
println!("Shape read: {shape:?}");
dctap.add_shape(&shape)
}
Ok(dctap)
}

pub fn from_reader<R: io::Read>(reader: R) -> Result<DCTap, TapError> {
let mut dctap = DCTap::new();
debug!("DCTap parsed: {:?}", dctap);
let mut tap_reader = TapReaderBuilder::new().flexible(true).from_reader(reader)?;
for maybe_shape in tap_reader.shapes() {
let shape = maybe_shape?;
println!("Shape read: {shape:?}");
dctap.add_shape(&shape)
}
Ok(dctap)
}
}

#[cfg(test)]
mod tests {
use crate::{PropertyId, TapShape, TapStatement};

use super::*;

#[test]
fn test_simple() {
let data = "\
shapeId,shapeLabel,propertyId,propertyLabel
Person,PersonLabel,knows,KnowsLabel
";
let dctap = DCTap::from_reader(data.as_bytes()).unwrap();
let mut expected_shape = TapShape::new();
expected_shape.set_shape_id(&ShapeId::new("Person"));
expected_shape.add_statement(TapStatement::new(PropertyId::new("knows")));

let mut expected_dctap = DCTap::new();
expected_dctap.add_shape(&expected_shape);
assert_eq!(dctap, expected_dctap);
}
}
30 changes: 30 additions & 0 deletions dctap/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,41 @@
pub mod dctap;
pub mod tap_config;
pub mod tap_error;
pub mod tap_headers;
pub mod tap_reader;
pub mod tap_shape;
pub mod tap_statement;

pub use crate::tap_config::*;
pub use crate::tap_error::*;
pub use crate::tap_reader::*;
pub use crate::tap_shape::*;
pub use crate::tap_statement::*;
pub use dctap::*;
use serde_derive::{Deserialize, Serialize};

#[derive(Deserialize, Serialize, Debug, PartialEq, Default, Clone)]
pub struct PropertyId {
str: String,
}

impl PropertyId {
pub fn new(str: &str) -> PropertyId {
PropertyId {
str: str.to_string(),
}
}
}

#[derive(Deserialize, Serialize, Debug, Hash, PartialEq, Eq, Clone)]
pub struct ShapeId {
str: String,
}

impl ShapeId {
pub fn new(str: &str) -> ShapeId {
ShapeId {
str: str.to_string(),
}
}
}
19 changes: 18 additions & 1 deletion dctap/src/tap_error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
use std::result;

use csv::StringRecord;
use thiserror::Error;

pub type Result<T> = result::Result<T, TapError>;

#[derive(Error, Debug)]
pub enum TapError {}
pub enum TapError {
#[error("CSV Error: {err}")]
RDFParseError {
#[from]
err: csv::Error,
},

#[error("Cannot obtain shape id with index {shape_id} from record {record:?}")]
NoShapeId {
shape_id: usize,
record: StringRecord,
},
}
46 changes: 46 additions & 0 deletions dctap/src/tap_headers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use crate::tap_error::Result;
use csv::StringRecord;
use tracing::debug;

#[derive(Debug, Default)]
pub(crate) struct TapHeaders {
shape_id: Option<usize>,
property_id: Option<usize>,
}

impl TapHeaders {
pub(crate) fn new() -> TapHeaders {
TapHeaders::default()
}

pub(crate) fn from_record(record: &StringRecord) -> Result<TapHeaders> {
let mut shape_id = None;
let mut property_id = None;

for (idx, field) in record.iter().enumerate() {
match clean(field).as_str() {
"SHAPEID" => shape_id = Some(idx),
"PROPERTYID" => property_id = Some(idx),
_ => {
debug!("Unknown field reading headers: {field}")
}
}
}
Ok(TapHeaders {
shape_id,
property_id,
})
}

pub fn shape_id(&self) -> Option<usize> {
self.shape_id
}

pub fn property_id(&self) -> Option<usize> {
self.property_id
}
}

fn clean(str: &str) -> String {
str.to_uppercase()
}
Loading