Skip to content

Commit

Permalink
Add support for reading from TAR archives to flatdata-rs (#182) (#209)
Browse files Browse the repository at this point in the history
* Add support for reading from TAR archives to flatdata-rs (#182)

Signed-off-by: Christian Ocker <[email protected]>
  • Loading branch information
fermeise authored Sep 30, 2021
1 parent 3edaa5d commit 183e382
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 8 deletions.
2 changes: 1 addition & 1 deletion flatdata-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ members = [
"lib",
"tests/features",
"tests/coappearances",
]
]
4 changes: 4 additions & 0 deletions flatdata-rs/lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@ edition = "2018"
[dependencies]
diff = "0.1.11"
memmap2 = "0.2.0"
tar = { version = "0.4", optional = true }
walkdir = "2.2.9"

[package.metadata.docs.rs]
all-features = true
2 changes: 1 addition & 1 deletion flatdata-rs/lib/src/filestorage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl MemoryMappedFileStorage {
/// # Examples
///
/// ```rust,no_run
/// use flatdata::{FileResourceStorage, Vector};
/// use flatdata::{FileResourceStorage, Vector};
/// use flatdata::test::{X, XBuilder};
///
/// let storage = FileResourceStorage::new("/root/to/my/archive");
Expand Down
17 changes: 16 additions & 1 deletion flatdata-rs/lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
//!
//! * data structures for writing data to archives: [`StructBuf`], [`Vector`], [`ExternalVector`], [`MultiVector`]
//! * data structures for reading data from archives: [`ArrayView`], [`MultiArrayView`]
//! * resource storage backends for using archives: [`MemoryResourceStorage`], [`FileResourceStorage`]
//! * resource storage backends for using archives: [`MemoryResourceStorage`], [`FileResourceStorage`], [`TarArchiveResourceStorage`]
//!
//! The generator is part of the main [heremaps/flatdata] repository,
//! the [`generate`] helper function is provided as a convenience wrapper.
Expand Down Expand Up @@ -123,12 +123,21 @@
//! List if prime factors for 1234 is [2, 617]
//! ```
//!
//! ## Optional Features
//!
//! The following are a list of [Cargo features][cargo-features] that can be
//! enabled or disabled:
//!
//! - **tar**: Enables support for reading TAR archives using the `TarArchiveResourceStorage`
//! struct.
//!
//! [heremaps/flatdata]: https://github.com/heremaps/flatdata
//! [schema]: https://github.com/heremaps/flatdata/blob/master/examples/coappearances/coappearances.flatdata
//! [usage]: https://github.com/heremaps/flatdata/blob/master/flatdata-rs/tests/coappearances/src/lib.rs
//! [Why flatdata?]: https://github.com/heremaps/flatdata/blob/master/docs/why-flatdata.md
//! [`MemoryResourceStorage`]: struct.MemoryResourceStorage.html
//! [`FileResourceStorage`]: struct.FileResourceStorage.html
//! [`TarArchiveResourceStorage`]: struct.TarArchiveResourceStorage.html
//! [`StructBuf`]: struct.StructBuf.html
//! [`Vector`]: struct.Vector.html
//! [`ExternalVector`]: struct.ExternalVector.html
Expand All @@ -137,6 +146,7 @@
//! [`MultiArrayView`]: struct.MultiArrayView.html
//! [`generate`]: fn.generate.html
//! [diag]: data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8%2BCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDIuNDAuMSAoMjAxNjEyMjUuMDMwNCkKIC0tPgo8IS0tIFRpdGxlOiBGbGF0ZGF0YURvdCBQYWdlczogMSAtLT4KPHN2ZyB3aWR0aD0iNTUycHQiIGhlaWdodD0iMTk4cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgNTUyLjAwIDE5OC4wMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI%2BCjxnIGlkPSJncmFwaDAiIGNsYXNzPSJncmFwaCIgdHJhbnNmb3JtPSJzY2FsZSgxIDEpIHJvdGF0ZSgwKSB0cmFuc2xhdGUoNCAxOTQpIj4KPHRpdGxlPkZsYXRkYXRhRG90PC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgcG9pbnRzPSItNCw0IC00LC0xOTQgNTQ4LC0xOTQgNTQ4LDQgLTQsNCIvPgo8ZyBpZD0iY2x1c3QxIiBjbGFzcz0iY2x1c3RlciI%2BCjx0aXRsZT5jbHVzdGVyX19wcmltZTwvdGl0bGU%2BCjxwb2x5Z29uIGZpbGw9IiNmN2Y3ZjciIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIiBwb2ludHM9IjgsLTggOCwtMTgyIDUzNiwtMTgyIDUzNiwtOCA4LC04Ii8%2BCjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMjQ3LjUiIHk9Ii0xNjYuMiIgZm9udC1mYW1pbHk9IkNvdXJpZXIgTmV3IiBmb250LXdlaWdodD0iYm9sZCIgZm9udC1zaXplPSIxNi4wMCIgZmlsbD0iIzUxNmQ3YiI%2BcHJpbWU8L3RleHQ%2BCjwvZz4KPGcgaWQ9ImNsdXN0MiIgY2xhc3M9ImNsdXN0ZXIiPgo8dGl0bGU%2BY2x1c3Rlcl9fcHJpbWVfQXJjaGl2ZTwvdGl0bGU%2BCjxwb2x5Z29uIGZpbGw9IiNlYmY4ZmYiIHN0cm9rZT0iIzg1ZDRmZiIgcG9pbnRzPSIxNiwtMTYgMTYsLTE0OCA1MjgsLTE0OCA1MjgsLTE2IDE2LC0xNiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjIzNy41IiB5PSItMTMyLjIiIGZvbnQtZmFtaWx5PSJDb3VyaWVyIE5ldyIgZm9udC13ZWlnaHQ9ImJvbGQiIGZvbnQtc2l6ZT0iMTYuMDAiIGZpbGw9IiM1MTZkN2IiPkFyY2hpdmU8L3RleHQ%2BCjwvZz4KPGcgaWQ9ImNsdXN0MyIgY2xhc3M9ImNsdXN0ZXIiPgo8dGl0bGU%2BY2x1c3Rlcl9fcHJpbWVfQXJjaGl2ZV9udW1iZXJzPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iI2M0ZTZmOCIgc3Ryb2tlPSIjODVkNGZmIiBzdHJva2Utd2lkdGg9IjAiIHBvaW50cz0iMjQsLTM2IDI0LC0xMTQgMjkxLC0xMTQgMjkxLC0zNiAyNCwtMzYiLz4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIxMzkiIHk9Ii0xMDMuOCIgZm9udC1mYW1pbHk9IkNvdXJpZXIgTmV3IiBmb250LXdlaWdodD0iYm9sZCIgZm9udC1zaXplPSI5LjAwIiBmaWxsPSIjNTE2ZDdiIj5udW1iZXJzPC90ZXh0Pgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjE0MS41IiB5PSItOTQuOCIgZm9udC1mYW1pbHk9IkNvdXJpZXIgTmV3IiBmb250LXN0eWxlPSJpdGFsaWMiIGZvbnQtc2l6ZT0iOS4wMCIgZmlsbD0iIzUxNmQ3YiI%2BVmVjdG9yPC90ZXh0Pgo8L2c%2BCjxnIGlkPSJjbHVzdDQiIGNsYXNzPSJjbHVzdGVyIj4KPHRpdGxlPmNsdXN0ZXJfX3ByaW1lX0FyY2hpdmVfZmFjdG9yczwvdGl0bGU%2BCjxwb2x5Z29uIGZpbGw9IiNjNGU2ZjgiIHN0cm9rZT0iIzg1ZDRmZiIgc3Ryb2tlLXdpZHRoPSIwIiBwb2ludHM9IjMxMSwtMjQgMzExLC0xMTQgNTIwLC0xMTQgNTIwLC0yNCAzMTEsLTI0Ii8%2BCjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMzk3IiB5PSItMTAzLjgiIGZvbnQtZmFtaWx5PSJDb3VyaWVyIE5ldyIgZm9udC13ZWlnaHQ9ImJvbGQiIGZvbnQtc2l6ZT0iOS4wMCIgZmlsbD0iIzUxNmQ3YiI%2BZmFjdG9yczwvdGV4dD4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSIzOTkuNSIgeT0iLTk0LjgiIGZvbnQtZmFtaWx5PSJDb3VyaWVyIE5ldyIgZm9udC1zdHlsZT0iaXRhbGljIiBmb250LXNpemU9IjkuMDAiIGZpbGw9IiM1MTZkN2IiPlZlY3RvcjwvdGV4dD4KPC9nPgo8IS0tIF9wcmltZV9BcmNoaXZlX251bWJlcnNfcHJpbWVfTnVtYmVyIC0tPgo8ZyBpZD0ibm9kZTEiIGNsYXNzPSJub2RlIj4KPHRpdGxlPl9wcmltZV9BcmNoaXZlX251bWJlcnNfcHJpbWVfTnVtYmVyPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iIzI1N2ZhZCIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgcG9pbnRzPSI0MS41LC02MiA0MS41LC03NCAyNzQuNSwtNzQgMjc0LjUsLTYyIDQxLjUsLTYyIi8%2BCjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iODguNSIgeT0iLTY2LjgiIGZvbnQtZmFtaWx5PSJDb3VyaWVyIE5ldyIgZm9udC1zaXplPSI5LjAwIiBmaWxsPSIjMDAwMDAwIj4gJiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7PC90ZXh0Pgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjE1Mi41IiB5PSItNjYuOCIgZm9udC1mYW1pbHk9IkNvdXJpZXIgTmV3IiBmb250LXdlaWdodD0iYm9sZCIgZm9udC1zaXplPSI5LjAwIiBmaWxsPSIjZWJmOGZmIj5OdW1iZXI8L3RleHQ%2BCjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMTg0LjUiIHk9Ii02Ni44IiBmb250LWZhbWlseT0iQ291cmllciBOZXciIGZvbnQtc2l6ZT0iOS4wMCIgZmlsbD0iIzAwMDAwMCI%2BICYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOzwvdGV4dD4KPHBvbHlnb24gZmlsbD0iI2ViZjhmZiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgcG9pbnRzPSI0MS41LC00OSA0MS41LC02MSAyNzQuNSwtNjEgMjc0LjUsLTQ5IDQxLjUsLTQ5Ii8%2BCjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDIuNSIgeT0iLTUzLjgiIGZvbnQtZmFtaWx5PSJDb3VyaWVyIE5ldyIgZm9udC1zaXplPSI5LjAwIiBmaWxsPSIjMDAwMDAwIj4gJiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7PC90ZXh0Pgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjEwNi41IiB5PSItNTMuOCIgZm9udC1mYW1pbHk9IkNvdXJpZXIgTmV3IiBmb250LXdlaWdodD0iYm9sZCIgZm9udC1zaXplPSI5LjAwIiBmaWxsPSIjNTE2ZDdiIj5maXJzdF9mYWN0b3JfcmVmPC90ZXh0Pgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjE5MS41IiB5PSItNTMuOCIgZm9udC1mYW1pbHk9IkNvdXJpZXIgTmV3IiBmb250LXNpemU9IjkuMDAiIGZpbGw9IiMwMDAwMDAiPjo8L3RleHQ%2BCjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMTk3LjUiIHk9Ii01My44IiBmb250LWZhbWlseT0iQ291cmllciBOZXciIGZvbnQtc2l6ZT0iOS4wMCIgZmlsbD0iIzU2OGMzYiI%2BdTMyPC90ZXh0Pgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjIxMy41IiB5PSItNTMuOCIgZm9udC1mYW1pbHk9IkNvdXJpZXIgTmV3IiBmb250LXNpemU9IjkuMDAiIGZpbGw9IiMwMDAwMDAiPjo8L3RleHQ%2BCjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMjE5LjUiIHk9Ii01My44IiBmb250LWZhbWlseT0iQ291cmllciBOZXciIGZvbnQtc2l6ZT0iOS4wMCIgZmlsbD0iI2QyMmQ3MiI%2BMzI8L3RleHQ%2BCjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMjMwLjUiIHk9Ii01My44IiBmb250LWZhbWlseT0iQ291cmllciBOZXciIGZvbnQtc2l6ZT0iOS4wMCIgZmlsbD0iIzAwMDAwMCI%2BICYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOzwvdGV4dD4KPC9nPgo8IS0tIF9wcmltZV9BcmNoaXZlX2ZhY3RvcnNfcHJpbWVfRmFjdG9yIC0tPgo8ZyBpZD0ibm9kZTIiIGNsYXNzPSJub2RlIj4KPHRpdGxlPl9wcmltZV9BcmNoaXZlX2ZhY3RvcnNfcHJpbWVfRmFjdG9yPC90aXRsZT4KPHBvbHlnb24gZmlsbD0iIzI1N2ZhZCIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgcG9pbnRzPSIzMjguNSwtNjMgMzI4LjUsLTc1IDUwMy41LC03NSA1MDMuNSwtNjMgMzI4LjUsLTYzIi8%2BCjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMzQ2LjUiIHk9Ii02Ny44IiBmb250LWZhbWlseT0iQ291cmllciBOZXciIGZvbnQtc2l6ZT0iOS4wMCIgZmlsbD0iIzAwMDAwMCI%2BICYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOzwvdGV4dD4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI0MTAuNSIgeT0iLTY3LjgiIGZvbnQtZmFtaWx5PSJDb3VyaWVyIE5ldyIgZm9udC13ZWlnaHQ9ImJvbGQiIGZvbnQtc2l6ZT0iOS4wMCIgZmlsbD0iI2ViZjhmZiI%2BRmFjdG9yPC90ZXh0Pgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjQ0Mi41IiB5PSItNjcuOCIgZm9udC1mYW1pbHk9IkNvdXJpZXIgTmV3IiBmb250LXNpemU9IjkuMDAiIGZpbGw9IiMwMDAwMDAiPiAmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDs8L3RleHQ%2BCjxwb2x5Z29uIGZpbGw9IiNlYmY4ZmYiIHN0cm9rZT0idHJhbnNwYXJlbnQiIHBvaW50cz0iMzI4LjUsLTUwIDMyOC41LC02MiA1MDMuNSwtNjIgNTAzLjUsLTUwIDMyOC41LC01MCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjMyOS41IiB5PSItNTQuOCIgZm9udC1mYW1pbHk9IkNvdXJpZXIgTmV3IiBmb250LXNpemU9IjkuMDAiIGZpbGw9IiMwMDAwMDAiPiAmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDs8L3RleHQ%2BCjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMzkzLjUiIHk9Ii01NC44IiBmb250LWZhbWlseT0iQ291cmllciBOZXciIGZvbnQtd2VpZ2h0PSJib2xkIiBmb250LXNpemU9IjkuMDAiIGZpbGw9IiM1MTZkN2IiPnZhbHVlPC90ZXh0Pgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjQyMC41IiB5PSItNTQuOCIgZm9udC1mYW1pbHk9IkNvdXJpZXIgTmV3IiBmb250LXNpemU9IjkuMDAiIGZpbGw9IiMwMDAwMDAiPjo8L3RleHQ%2BCjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDI2LjUiIHk9Ii01NC44IiBmb250LWZhbWlseT0iQ291cmllciBOZXciIGZvbnQtc2l6ZT0iOS4wMCIgZmlsbD0iIzU2OGMzYiI%2BdTMyPC90ZXh0Pgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjQ0Mi41IiB5PSItNTQuOCIgZm9udC1mYW1pbHk9IkNvdXJpZXIgTmV3IiBmb250LXNpemU9IjkuMDAiIGZpbGw9IiMwMDAwMDAiPjo8L3RleHQ%2BCjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDQ4LjUiIHk9Ii01NC44IiBmb250LWZhbWlseT0iQ291cmllciBOZXciIGZvbnQtc2l6ZT0iOS4wMCIgZmlsbD0iI2QyMmQ3MiI%2BMzI8L3RleHQ%2BCjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iNDU5LjUiIHk9Ii01NC44IiBmb250LWZhbWlseT0iQ291cmllciBOZXciIGZvbnQtc2l6ZT0iOS4wMCIgZmlsbD0iIzAwMDAwMCI%2BICYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOyYjMTYwOzwvdGV4dD4KPHBvbHlnb24gZmlsbD0iI2ViZjhmZiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgcG9pbnRzPSIzMjguNSwtMzcgMzI4LjUsLTQ5IDUwMy41LC00OSA1MDMuNSwtMzcgMzI4LjUsLTM3Ii8%2BCjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMzMyIiB5PSItNDEuOCIgZm9udC1mYW1pbHk9IkNvdXJpZXIgTmV3IiBmb250LXNpemU9IjkuMDAiIGZpbGw9IiMwMDAwMDAiPiAmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDsmIzE2MDs8L3RleHQ%2BCjx0ZXh0IHRleHQtYW5jaG9yPSJzdGFydCIgeD0iMzk2IiB5PSItNDEuOCIgZm9udC1mYW1pbHk9IkNvdXJpZXIgTmV3IiBmb250LXdlaWdodD0iYm9sZCIgZm9udC1zaXplPSI5LjAwIiBmaWxsPSIjNTE2ZDdiIj5jb3VudDwvdGV4dD4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI0MjMiIHk9Ii00MS44IiBmb250LWZhbWlseT0iQ291cmllciBOZXciIGZvbnQtc2l6ZT0iOS4wMCIgZmlsbD0iIzAwMDAwMCI%2BOjwvdGV4dD4KPHRleHQgdGV4dC1hbmNob3I9InN0YXJ0IiB4PSI0MjkiIHk9Ii00MS44IiBmb250LWZhbWlseT0iQ291cmllciBOZXciIGZvbnQtc2l6ZT0iOS4wMCIgZmlsbD0iIzU2OGMzYiI%2BdTMyPC90ZXh0Pgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjQ0NSIgeT0iLTQxLjgiIGZvbnQtZmFtaWx5PSJDb3VyaWVyIE5ldyIgZm9udC1zaXplPSI5LjAwIiBmaWxsPSIjMDAwMDAwIj46PC90ZXh0Pgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjQ1MSIgeT0iLTQxLjgiIGZvbnQtZmFtaWx5PSJDb3VyaWVyIE5ldyIgZm9udC1zaXplPSI5LjAwIiBmaWxsPSIjZDIyZDcyIj44PC90ZXh0Pgo8dGV4dCB0ZXh0LWFuY2hvcj0ic3RhcnQiIHg9IjQ1NyIgeT0iLTQxLjgiIGZvbnQtZmFtaWx5PSJDb3VyaWVyIE5ldyIgZm9udC1zaXplPSI5LjAwIiBmaWxsPSIjMDAwMDAwIj4gJiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7JiMxNjA7PC90ZXh0Pgo8L2c%2BCjwhLS0gX3ByaW1lX0FyY2hpdmVfbnVtYmVyc19wcmltZV9OdW1iZXImIzQ1OyZndDtfcHJpbWVfQXJjaGl2ZV9mYWN0b3JzX3ByaW1lX0ZhY3RvciAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI%2BCjx0aXRsZT5fcHJpbWVfQXJjaGl2ZV9udW1iZXJzX3ByaW1lX051bWJlcjpwb3J0X19wcmltZV9BcmNoaXZlX251bWJlcnNfcHJpbWVfTnVtYmVyX2ZpcnN0X2ZhY3Rvcl9yZWYmIzQ1OyZndDtfcHJpbWVfQXJjaGl2ZV9mYWN0b3JzX3ByaW1lX0ZhY3RvcjwvdGl0bGU%2BCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzI1N2ZhZCIgZD0iTTI3OC41NDgzLC01NS4wMDE0QzI5MC4wMTgsLTU1LjAwOSAzMDEuOTM1OCwtNTUuMDQ4IDMxMy43NDI2LC01NS4xMDY1Ii8%2BCjxlbGxpcHNlIGZpbGw9IiMyNTdmYWQiIHN0cm9rZT0iIzI1N2ZhZCIgY3g9IjI3Ni41IiBjeT0iLTU1LjAwMDciIHJ4PSIyIiByeT0iMiIvPgo8cG9seWdvbiBmaWxsPSIjMjU3ZmFkIiBzdHJva2U9IiMyNTdmYWQiIHBvaW50cz0iMzEzLjc4NTEsLTU2Ljg1NjcgMzE4Ljc5NDIsLTU1LjEzMjggMzEzLjgwMzQsLTUzLjM1NjcgMzEzLjc4NTEsLTU2Ljg1NjciLz4KPC9nPgo8L2c%2BCjwvc3ZnPg%3D%3D
//! [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section
#![deny(missing_docs, missing_debug_implementations, warnings)]

/// Number of elements in `ArrayView`, `MultiArrayView`, and `Vector` to show
Expand All @@ -159,6 +169,8 @@ mod multivector;
mod rawdata;
mod storage;
mod structs;
#[cfg(feature = "tar")]
mod tarstorage;
mod vector;

#[doc(hidden)]
Expand All @@ -183,3 +195,6 @@ pub use crate::{
structs::*,
vector::*,
};

#[cfg(feature = "tar")]
pub use crate::tarstorage::TarArchiveResourceStorage;
133 changes: 133 additions & 0 deletions flatdata-rs/lib/src/tarstorage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
use crate::storage::{ResourceStorage, StorageHandle, Stream};

use memmap2::Mmap;
use std::{
collections::HashMap,
fs::File,
io,
ops::Range,
path::{Path, PathBuf},
slice,
sync::Arc,
};

/// Internal storage of file entries in tar archive.
#[derive(Debug)]
struct MemoryMappedTarArchiveStorage {
archive_map: Mmap,
file_ranges: HashMap<PathBuf, Range<usize>>,
}

impl MemoryMappedTarArchiveStorage {
pub fn new(tar_path: &Path) -> Result<Self, io::Error> {
let file = File::open(tar_path)?;
let archive_map = unsafe { Mmap::map(&file)? };
let mut archive = tar::Archive::new(&archive_map[..]);

let file_ranges = archive
.entries()?
.map(|entry| {
let entry = entry?;
let path = entry.path()?;
let path = if let Ok(stripped_path) = path.strip_prefix(".") {
stripped_path.to_path_buf()
} else {
path.to_path_buf()
};
let offset = entry.raw_file_position() as usize;
let size = entry.size() as usize;
if entry.header().entry_size()? != entry.size() {
// We can only memory-map contiguous files
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Sparse files are not supported",
));
}

Ok((path, offset..offset + size))
})
.collect::<Result<HashMap<PathBuf, Range<usize>>, io::Error>>()?;

Ok(Self {
archive_map,
file_ranges,
})
}

pub fn read(&self, path: &Path) -> Option<&[u8]> {
self.file_ranges.get(path).map(|range| {
// We cannot prove to Rust that the buffer will live as long as the storage
// (we never delete mappings), so we need to manually extend lifetime
let extended_lifetime_archive_map =
unsafe { slice::from_raw_parts(self.archive_map.as_ptr(), self.archive_map.len()) };

&extended_lifetime_archive_map[range.clone()]
})
}
}

/// Read-only resource storage on disk using a memory mapped tar archive.
///
/// Used to read flatdata archives from a tar archive on disk.
///
/// # Examples
///
/// ```rust,no_run
/// use flatdata::{TarArchiveResourceStorage, Vector};
/// use flatdata::test::X;
///
/// let storage = TarArchiveResourceStorage::new("/root/to/my/archive.tar")
/// .expect("failed to read tar archive");
/// let archive = X::open(storage).expect("failed to open");
/// // read data
/// archive.data();
/// ```
#[derive(Debug)]
pub struct TarArchiveResourceStorage {
storage: Arc<MemoryMappedTarArchiveStorage>,
sub_path: PathBuf,
}

impl TarArchiveResourceStorage {
/// Create a memory mapped tar archive resource storage for a tar archive at a given path.
pub fn new<P: Into<PathBuf>>(tar_path: P) -> Result<Arc<Self>, io::Error> {
Ok(Arc::new(Self {
storage: Arc::new(MemoryMappedTarArchiveStorage::new(&tar_path.into())?),
sub_path: PathBuf::new(),
}))
}
}

impl ResourceStorage for TarArchiveResourceStorage {
fn subdir(&self, dir: &str) -> StorageHandle {
Arc::new(Self {
storage: self.storage.clone(),
sub_path: self.sub_path.join(dir),
})
}

fn exists(&self, resource_name: &str) -> bool {
self.storage
.read(&self.sub_path.join(resource_name))
.is_some()
}

fn read_resource(&self, resource_name: &str) -> Result<&[u8], io::Error> {
let resource_path = self.sub_path.join(resource_name);
if let Some(data) = self.storage.read(&resource_path) {
Ok(data)
} else {
Err(io::Error::new(
io::ErrorKind::NotFound,
String::from(resource_path.to_str().unwrap_or(resource_name)),
))
}
}

fn create_output_stream(&self, _resource_name: &str) -> Result<Box<dyn Stream>, io::Error> {
Err(io::Error::new(
io::ErrorKind::Other,
"Writing to tar archives is not supported",
))
}
}
2 changes: 1 addition & 1 deletion flatdata-rs/rustfmt.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ wrap_comments = true

ignore = [
"lib/src/lib.rs",
]
]
3 changes: 3 additions & 0 deletions flatdata-rs/tests/coappearances/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ flatdata = { path = "../../lib" }

[build-dependencies]
flatdata = { path = "../../lib" }

[features]
tar = ["flatdata/tar"]
Binary file not shown.
23 changes: 19 additions & 4 deletions flatdata-rs/tests/coappearances/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ use std::{env, fs, io::Read, path, str};

pub mod coappearances;

#[test]
fn read_and_validate_coappearances() -> Result<(), std::str::Utf8Error> {
let storage =
flatdata::FileResourceStorage::new(path::PathBuf::from("assets/karenina.archive"));
fn read_and_validate_coappearances(
storage: flatdata::StorageHandle,
) -> Result<(), std::str::Utf8Error> {
let g = coappearances::Graph::open(storage).expect("invalid archive");
println!("{:?}", g);

Expand Down Expand Up @@ -127,6 +126,22 @@ fn read_and_validate_coappearances() -> Result<(), std::str::Utf8Error> {
Ok(())
}

#[test]
fn read_and_validate_coappearances_from_file_storage() -> Result<(), std::str::Utf8Error> {
let storage =
flatdata::FileResourceStorage::new(path::PathBuf::from("assets/karenina.archive"));
read_and_validate_coappearances(storage)
}

#[test]
#[cfg(feature = "tar")]
fn read_and_validate_coappearances_from_tar_archive_storage() -> Result<(), std::str::Utf8Error> {
let storage =
flatdata::TarArchiveResourceStorage::new(path::PathBuf::from("assets/karenina.tar"))
.expect("failed to read tar archive");
read_and_validate_coappearances(storage)
}

fn check_files(name_a: &path::Path, name_b: &path::Path) {
let mut fa = fs::File::open(name_a).unwrap();
let mut buf_a = Vec::new();
Expand Down

0 comments on commit 183e382

Please sign in to comment.